You are on page 1of 2697

Contents

PlayFab
What is PlayFab?
Game Manager
What is Game Manager?
Quickstart
Reference
Tutorials
Create a PlayFab Account
API Feature Settings in the PlayFab Game Manager
Audit Logs
Encrypted Logins
Player Encryption Services
PlayFab user roles
Secret Key Management
Two-Factor Authentication
Build
Authentication
PlayFab Authentication
What is Authentication
Player login
Overview
Login basics and Best Practices
Quickstart
Platform specific authentication
Overview
Tutorials
Running an HTTP server for testing
Setting up PlayFab authentication using Facebook and HTML5
Setting up PlayFab authentication using Facebook and Unity
Setting up PlayFab authentication using Google and HTML5
Setting up PlayFab authentication using Google Play Games Sign-In in Unity
Setting up PlayFab authentication using Kongregate and HTML5
Setting up PlayFab authentication using Kongregate and Unity
Setting up PlayFab authentication in Phaser.io
Setting up PlayFab authentication using Steam and Unity
Setting up PlayFab authentication using Twitch and HTML5
Setting up PlayFab authentication using Universal Windows Platform
Setup Sign In with Apple for PlayFab
Integrating the Universal Windows Platform with PlayFab
Azure Active Directory Authentication for Game Manager
Overview
Automation
PlayFab Automation
What is Automation
CloudScript (Legacy)
Overview
Quickstart
Tutorials
ES6 features in CloudScript (Legacy)
Handling errors in CloudScript (Legacy)
Making Webhook calls from CloudScript (Legacy)
SDK error handling best practices
Writing custom CloudScript (Legacy)
CloudScript using Azure Functions
Overview
Quickstart
Tutorials
Using CloudScript context models
Local Debugging for Cloudscript using Azure Functions
Debugging CloudScript using Azure Functions with Visual Studio Code
Debugging CloudScript using Azure Functions with Visual Studio
Debugging CloudScript using Azure Functions with the Azure Portal
Actions and rules
Overview
Quickstart
Tutorials
Bulk Actions for an entire player segment
Using CloudScript actions with PlayStream
Scheduled tasks
Overview
Quickstart
Playstream
Overview
Custom Tags
PlayStream with entity events
Rewarded Ads
Overview
Quickstart
Multiplayer
PlayFab Multiplayer
Introduction to Multiplayer
Servers
Overview
Host multiplayer games
Get started
Enable feature for game title
Create VMs
Create your first server
Build definition
Builds overview
Servers overview
Game server and container basics
Terminology
Author a game server
Author a game server build
Integrate game server build with GSDK
Determining required DLLs
Integrate Unity with GSDK
Manage VMs
Deploy builds using Game Manager
Deploy builds using PowerShell/API
Create Linux container images
Server build lifecycle
Build region lifecycle
Game server lifecycle
OS patch level updates for Windows
Use aliases to aggregate and manage multiple VM builds
Archive and retrieve server logs
VM performance metrics (preview)
Debugging game servers
LocalMultiplayerAgent
LocalMultiplayerAgent Overview
Debug Process-based game server
Debug Container-based game server
Connect directly to debug game servers
Locally debugging game servers and integration
Enabling automatic collection of crash dump
Attaching a profiler
Scaling game servers
Scaling Standby
Dynamic Standby
Scheduled Standby
Scaling Programmatically
Connecting clients and requesting servers
Use QoS beacons to measure player latency to Azure
Allocate game servers and connect VS debugging tools
Connecting clients to game servers
Limits and billing
Request and review quota changes
Get increased core limits and additional Azure regions
Enterprise Agreement (EA) billing
PlayFab services billing
Detailed price sheet
Incident response commitment
Monitor server capacity
Track server consumption
Samples and resources
Samples and resources
Wrapper
MpsAllocator
Windows Runner C#
Deploy Windows builds using Game Manager
Deploy Windows builds using PowerShell/API
SDKs
GSDKs
Unreal GSDK
Overview
Unreal Plugin GSDK
Matchmaking
Overview
Quickstart - Client SDK
Quickstart - REST API
Tutorials
Configuring matchmaking queues
Displaying queue statistics in your title
Handling common error cases
Integrating with PlayFab Multiplayer Servers
Matchmaking scenario and configuration examples
Specifying attributes with your tickets
Using server backfill tickets
Analyzing Your Matchmaking Queue Usage
Workaround for peer-to-peer connection
Lobby and Matchmaking real-time notifications
Lobby
Overview
Quickstart
Tutorials
Create a lobby
Invites
Join lobbies
Lobby properties
Create searchable lobbies
Find lobbies
Owner requirements and privileges
Lobby ownership changes
Use lobby and matchmaking together
Lobby and Matchmaking real-time notifications
Reference
Client SDK reference
Release notes
C++ SDK Release notes
Party
Overview
Features
Get started
Get started
Samples
Enable Party in Game Manager
Party SDK quickstart
Party objects and their relationships
Chat
Overview
Accessibility
Text-to-speech and text input UX guidelines
Speech-to-text and text display UX guidelines
Chat permissions and muting
Custom voice effects via real-time audio manipulation
Troubleshooting voice chat
Using text moderation
Networking and security
Invitations and the security model
Integrate discovery with Party
Transport options
Direct peer-to-peer connections
Port Usage and Firewall Requirements
Multiple network usage
Pricing
Regions and QoS
QoS
Supported Azure regions
Release notes
Insights
PlayFab Insights
Overview
Connectivity
Overview
Creating an Azure Application for Insights
Connecting Power BI to Insights
Connecting Kusto Explorer to Insights
Connecting Azure Data Explorer to Insights
Connecting Azure Data Factory to Insights
Connecting Grafana to Insights
Connecting Python to Insights
Connecting Kusto C# SDK to Insights
Data Explorer
Overview
Quickstart
Tutorials
Getting started with Data Explorer basic mode
Getting started with Data Explorer advanced mode
Schemas
Overview
Quickstart
Tutorials
About the events.all table
Performance Levels and Retention
Insights Scheduled Scaling
Exporting Data
Insights Management Commands
Pricing
Best Practices and FAQ
Social
PlayFab Social
What is Social
Friends
Overview
Quickstart
Tutorials
Friends Leaderboards
Groups, Guilds and Clans
Overview
Quickstart
Tutorials
Using Shared Group Data
Tournaments and Leaderboards
Overview
Quickstart
Tutorials
Accessing Archived Tournament Results
Using Prize Tables
Using resettable statistics and leaderboards
Using the Profile for Advanced Leaderboards
Friends Leaderboards
Trading
Overview
Quickstart
Leaderboards v2 [BETA]
Overview
Quickstart
Tutorials
Getting Started
Child Leaderboards
Engagement
Economy
PlayFab Economy
Economy
Overview
Quickstart
Tutorials
Coupons and Promotions
Currencies
Getting a Player's Value-to-Date (VTD)
Getting started with PlayFab, Unity IAP, and Android
Non-Receipt Payment Processing
Items
Overview
Quickstart
Tutorials
Catalogs
Drop Tables
Timed Consumables
Stores
Overview
Quickstart
Tutorials
Best Practices for Store segmentation
Custom Stores for Player Segments
Stores and Sales
User Generated Content
Overview
Quickstart
Search
Moderation
Ratings and Reviews
Settings
Item Visibility
ETags
Pricing
Limits
Tutorials
Publish UGC
Engagement (Player retention)
PlayFab Engagement
What is Engagement
Title News
Overview
Quickstart
Tutorials
Setting default languages
Push Notifications Templates
Overview
Quickstart
Tutorials
Getting Started with Android Push Notifications
Push notification templates
Push Notifications for Android
Push Notifications for iOS
Email Templates
Overview
Quickstart
Tutorials
Localized email templates
Setting up an SMTP server with add-ons
Using a rule to verify a contact e-mail address
Using e-mail templates
Analyze
Data
PlayFab Data
What is PlayFab Data
Player Data
Overview
Quickstart
How to set internal player data
How to get internal player data
How to set read-only player data
How to get read-only player data
How to modify read-only or internal player data from CloudScript
How to use player publisher data to grant a reward for playing multiple titles
Tutorials
Getting Player Profiles
Player Inventory
Using the Players page
Using Player details
Player Logins report
Player Ban System
Player Segments
Player Segment configuration
PlayFab GDPR
Using player statistics
Title Data
Overview
Quickstart
Tutorials
Using publisher data
Entities
Overview
Quickstart
Available built-in Entity types
Migration information
Entity files
Use entity objects to store player data
Tutorials
Entity Groups
Entity API Restructure Upgrade Tutorial
Data Connections
Overview
Quickstart
Manage Events with sampling
Overview
Quickstart
Content Delivery Network (Legacy)
Overview
Quickstart
Webhooks
Analytics
PlayFab Analytics
What is PlayFab Analytics
Experiments
Overview
Quickstart
Exclusion Groups
Recommendations
Key-terms
Billing for Experiments
Metrics
Overview
Metrics and terminology
Real-Time Analytics - Core Concepts
Quickstart
Tutorials
Generating PlayStream events
Set up an Amazon S3 bucket
Sessions
Reports
Overview
Quickstart
Tutorials
Daily A/B Test KPI Report
Daily Abuse Reports History Report
Daily and Monthly CDN Usage Report
Daily and Monthly Top Items Report
Daily and Monthly Top Spender Report
Daily and Monthly Top Details Report
Daily and Monthly Rolling 30-Day Overview and Totals Reports
Thirty-day New User Conversion Report
Thirty-day New User Retention Report
Thirty-day Retention Report
Segmentation
Overview
Quickstart
Tutorials
Segment Configuration
Export Players of a Segment
A/B testing
Overview
Quickstart
Tutorials
A/B testing with Stores and test buckets
A/B testing with Title data
Personas
Business Intelligence
Developer
Pricing
PlayFab Pricing
Billing Summary and Base Rates
Development Mode Titles
Pricing Meters
Meters Overview
Profile Reads
Profile Writes
Content & Configuration Reads
Content & Configuration Writes
Technical Support
Updating Account Pricing
Account Upgrades
Title Launches
Consumption Best Practices
Roadmap
Roadmap
Release notes
2022 SDK Release Notes
2021 SDK Release Notes
2020 SDK Release Notes
2019 SDK Release Notes
2018 SDK Release Notes
2017 SDK Release Notes
2016 SDK Release Notes
2015 SDK Release Notes
Reference
REST API
Overview
Reference
Real-time notifications for Lobby and Matchmaking
Overview
SignalR Hub
Subscribing To Resources
Client methods
ReceiveMessage
ReceiveSubscriptionChangeMessage
Server methods
AddEntityToSession
EndSession
RemoveEntityFromSession
StartOrRecoverSession
Type reference
EndSessionRequest
EndSessionResponse
Message
ResponseStatus
SharedSessionRequest
SharedSessionResponse
StartOrRecoverSessionRequest
StartOrRecoverSessionResponse
SubscriptionChangeMessage
Party C/C++ API
Overview
Classes
PartyAudioManipulationSinkStream
Methods
GetConfiguration
GetFormat
SubmitBuffer
GetCustomContext
SetCustomContext
PartyAudioManipulationSourceStream
Methods
GetConfiguration
GetFormat
GetAvailableBufferCount
GetNextBuffer
ReturnBuffer
GetCustomContext
SetCustomContext
PartyChatControl
Methods
GetLocal
GetDevice
GetEntityId
GetNetworks
GetCustomContext
SetCustomContext
ConfigureAudioManipulationVoiceStream
GetAudioManipulationVoiceStream
PartyDevice
Methods
GetLocal
GetChatControls
GetCustomContext
SetCustomContext
PartyEndpoint
Methods
GetLocal
GetEntityId
GetNetwork
GetDevice
GetUniqueIdentifier
GetCustomContext
SetCustomContext
PartyInvitation
Methods
GetCreatorEntityId
GetInvitationConfiguration
GetCustomContext
SetCustomContext
PartyLocalChatControl
Methods
GetLocalUser
SetPermissions
GetPermissions
SendText
SetAudioInput
GetAudioInput
SetAudioOutput
GetAudioOutput
PopulateAvailableTextToSpeechProfiles
GetAvailableTextToSpeechProfiles
SetTextToSpeechProfile
GetTextToSpeechProfile
SynthesizeTextToSpeech
GetLanguage
SetTranscriptionOptions
GetTranscriptionOptions
SetTextChatOptions
GetTextChatOptions
SetAudioRenderVolume
GetAudioRenderVolume
SetAudioInputMuted
GetAudioInputMuted
SetIncomingAudioMuted
GetIncomingAudioMuted
SetIncomingTextMuted
GetIncomingTextMuted
GetLocalChatIndicator
GetChatIndicator
ConfigureAudioManipulationCaptureStream
GetAudioManipulationCaptureStream
ConfigureAudioManipulationRenderStream
GetAudioManipulationRenderStream
PartyLocalDevice
Methods
CreateChatControl
DestroyChatControl
PartyLocalEndpoint
Methods
GetLocalUser
SendMessage
FlushMessages
GetEndpointStatistics
PartyLocalUser
Methods
GetEntityId
UpdateEntityToken
GetCustomContext
SetCustomContext
PartyManager
Methods
GetSingleton
SetOption
GetOption
GetErrorMessage
SerializeNetworkDescriptor
DeserializeNetworkDescriptor
SetMemoryCallbacks
GetMemoryCallbacks
SetProfilingCallbacksForMethodEntryExit
GetProfilingCallbacksForMethodEntryExit
SetThreadAffinityMask
GetThreadAffinityMask
SetWorkMode
GetWorkMode
Initialize
Cleanup
StartProcessingStateChanges
FinishProcessingStateChanges
DoWork
GetRegions
CreateNewNetwork
ConnectToNetwork
GetLocalDevice
CreateLocalUser
DestroyLocalUser
GetLocalUsers
GetNetworks
GetChatControls
PartyNetwork
Methods
AuthenticateLocalUser
RemoveLocalUser
CreateInvitation
RevokeInvitation
GetInvitations
CreateEndpoint
DestroyEndpoint
LeaveNetwork
GetEndpoints
FindEndpointByUniqueIdentifier
GetDevices
GetLocalUsers
GetNetworkDescriptor
GetNetworkConfiguration
ConnectChatControl
DisconnectChatControl
GetChatControls
GetNetworkStatistics
GetCustomContext
SetCustomContext
GetDeviceConnectionType
PartyTextToSpeechProfile
Methods
GetIdentifier
GetName
GetLanguageCode
GetGender
GetCustomContext
SetCustomContext
Callbacks
PartyAllocateMemoryCallback
PartyFreeMemoryCallback
PartyProfilingMethodEntranceCallback
PartyProfilingMethodExitCallback
Structures
PartyAudioFormat
PartyAudioManipulationSinkStreamConfiguration
PartyAudioManipulationSourceStreamConfiguration
PartyDataBuffer
PartyInvitationConfiguration
PartyLocalUdpSocketBindAddressConfiguration
PartyMutableDataBuffer
PartyNetworkConfiguration
PartyNetworkDescriptor
PartyProfilingMethodEntranceEventData
PartyProfilingMethodExitEventData
PartyRegion
PartySendMessageQueuingConfiguration
PartyTranslation
State changes
PartyAuthenticateLocalUserCompletedStateChange
PartyChatControlCreatedStateChange
PartyChatControlDestroyedStateChange
PartyChatControlJoinedNetworkStateChange
PartyChatControlLeftNetworkStateChange
PartyChatTextReceivedStateChange
PartyConfigureAudioManipulationCaptureStreamCompletedStateChange
PartyConfigureAudioManipulationRenderStreamCompletedStateChange
PartyConfigureAudioManipulationVoiceStreamCompletedStateChange
PartyConnectChatControlCompletedStateChange
PartyConnectToNetworkCompletedStateChange
PartyCreateChatControlCompletedStateChange
PartyCreateEndpointCompletedStateChange
PartyCreateInvitationCompletedStateChange
PartyCreateNewNetworkCompletedStateChange
PartyDataBuffersReturnedStateChange
PartyDestroyChatControlCompletedStateChange
PartyDestroyEndpointCompletedStateChange
PartyDestroyLocalUserCompletedStateChange
PartyDisconnectChatControlCompletedStateChange
PartyEndpointCreatedStateChange
PartyEndpointDestroyedStateChange
PartyEndpointMessageReceivedStateChange
PartyInvitationCreatedStateChange
PartyInvitationDestroyedStateChange
PartyLeaveNetworkCompletedStateChange
PartyLocalChatAudioInputChangedStateChange
PartyLocalChatAudioOutputChangedStateChange
PartyLocalUserRemovedStateChange
PartyNetworkConfigurationMadeAvailableStateChange
PartyNetworkDescriptorChangedStateChange
PartyNetworkDestroyedStateChange
PartyPopulateAvailableTextToSpeechProfilesCompletedStateChange
PartyRegionsChangedStateChange
PartyRemoteDeviceCreatedStateChange
PartyRemoteDeviceDestroyedStateChange
PartyRemoteDeviceJoinedNetworkStateChange
PartyRemoteDeviceLeftNetworkStateChange
PartyRemoveLocalUserCompletedStateChange
PartyRevokeInvitationCompletedStateChange
PartySetChatAudioInputCompletedStateChange
PartySetChatAudioOutputCompletedStateChange
PartySetTextChatOptionsCompletedStateChange
PartySetTextToSpeechProfileCompletedStateChange
PartySetTranscriptionOptionsCompletedStateChange
PartyStateChange
PartySynthesizeTextToSpeechCompletedStateChange
PartyVoiceChatTranscriptionReceivedStateChange
Enumerations
PartyAudioDeviceSelectionType
PartyAudioInputState
PartyAudioOutputState
PartyAudioSampleType
PartyAudioSourceType
PartyChatControlChatIndicator
PartyChatPermissionOptions
PartyChatTextReceivedOptions
PartyDestroyedReason
PartyDeviceConnectionType
PartyDirectPeerConnectivityOptions
PartyEndpointStatistic
PartyGender
PartyInvitationRevocability
PartyLocalChatControlChatIndicator
PartyLocalUdpSocketBindAddressOptions
PartyLocalUserRemovedReason
PartyMessageReceivedOptions
PartyNetworkStatistic
PartyOption
PartySendMessageOptions
PartyStateChangeResult
PartyStateChangeType
PartySynthesizeTextToSpeechType
PartyTextChatFilterLevel
PartyTextChatOptions
PartyThreadId
PartyTranslationReceivedOptions
PartyVoiceChatTranscriptionOptions
PartyVoiceChatTranscriptionPhraseType
PartyWorkMode
Typedefs
Party Unity API
Overview
Classes
PlayFabLocalPlayer
Properties
IsChatControlAvailable
LanguageCode
PlatformSpecificUserId
PlayFabPlayer
Properties
ChatState
EntityKey
IsLocal
IsMuted
VoiceLevel
PlayFabMultiplayerManager
Properties
LocalPlayer
LogLevel
NetworkId
RemotePlayers
SpeechToTextMode
State
TextToSpeechMode
TranslateChat
Methods
SendChatMessage
SendChatMessageToAllPlayers
CreateAndJoinNetwork
Get
LeaveNetwork
SendDataMessage
SendDataMessageToAllPlayers
UpdateEntityToken
Events
partyunityonchatmessagereceived
partyunityondatamessagereceived
partyunityondatamessagenocopyreceived
partyunityonerroreventhandler
partyunityonnetworkchanged
partyunityonnetworkjoined
partyunityonnetworkleft
partyunityonremoteplayerjoined
partyunityonremoteplayerleft
Enums
AccessibilityMode
ChatMessageType
ChatMessageState
DeliveryOption
DirectPeerConnectivityOptions
LogLevelType
PlayFabMultiplayerManagerErrorType
PlayFabMultiplayerManagerState
Party Xbox Live Helper
Overview
Classes
PartyXblChatUser
Methods
GetLocal
GetXboxUserId
GetCustomContext
SetCustomContext
PartyXblLocalChatUser
Methods
GetAccessibilitySettings
GetRequiredChatPermissionInfo
GetCrossNetworkCommunicationPrivacySetting
PartyXblManager
Methods
GetSingleton
GetErrorMessage
SetMemoryCallbacks
GetMemoryCallbacks
SetThreadAffinityMask
GetThreadAffinityMask
Initialize
Cleanup
StartProcessingStateChanges
FinishProcessingStateChanges
CompleteGetTokenAndSignatureRequest
CreateLocalChatUser
CreateRemoteChatUser
DestroyChatUser
GetChatUsers
LoginToPlayFab
GetEntityIdsFromXboxLiveUserIds
Structures
PartyXblAccessibilitySettings
PartyXblChatPermissionInfo
PartyXblHttpHeader
PartyXblXboxUserIdToPlayFabEntityIdMapping
State changes
PartyXblCreateLocalChatUserCompletedStateChange
PartyXblGetEntityIdsFromXboxLiveUserIdsCompletedStateChange
PartyXblLocalChatUserDestroyedStateChange
PartyXblLoginToPlayFabCompletedStateChange
PartyXblRequiredChatPermissionInfoChangedStateChange
PartyXblStateChange
PartyXblTokenAndSignatureRequestedStateChange
Enumerations
PartyXblChatPermissionMaskReason
PartyXblCrossNetworkCommunicationPrivacySetting
PartyXblLocalChatUserDestroyedReason
PartyXblStateChangeResult
PartyXblStateChangeType
PartyXblThreadId
Typedefs
Lobby and Matchmaking C/C++ API
Overview
PFMultiplayer overview
PFLobby overview
PFMatchmaking overview
Functions
PFMultiplayerGetErrorMessage
PFMultiplayerInitialize
PFMultiplayerSetEntityToken
PFMultiplayerSetMemoryCallbacks
PFMultiplayerSetThreadAffinityMask
PFMultiplayerUninitialize
PFLobbyAddMember
PFLobbyForceRemoveMember
PFLobbyGetAccessPolicy
PFLobbyGetConnectionString
PFLobbyGetCustomContext
PFLobbyGetLobbyId
PFLobbyGetLobbyProperty
PFLobbyGetLobbyPropertyKeys
PFLobbyGetMaxMemberCount
PFLobbyGetMemberProperty
PFLobbyGetMemberPropertyKeys
PFLobbyGetMembers
PFLobbyGetMembershipLock
PFLobbyGetOwner
PFLobbyGetOwnerMigrationPolicy
PFLobbyGetSearchProperty
PFLobbyGetSearchPropertyKeys
PFLobbyLeave
PFLobbyPostUpdate
PFLobbySendInvite
PFLobbySetCustomContext
PFMultiplayerCreateAndJoinLobby
PFMultiplayerFindLobbies
PFMultiplayerFinishProcessingLobbyStateChanges
PFMultiplayerGetLobbyInviteListenerStatus
PFMultiplayerJoinArrangedLobby
PFMultiplayerJoinLobby
PFMultiplayerStartListeningForLobbyInvites
PFMultiplayerStartProcessingLobbyStateChanges
PFMultiplayerStopListeningForLobbyInvites
PFMatchmakingTicketCancel
PFMatchmakingTicketGetMatch
PFMatchmakingTicketGetStatus
PFMatchmakingTicketGetTicketId
PFMultiplayerCreateMatchmakingTicket
PFMultiplayerDestroyMatchmakingTicket
PFMultiplayerFinishProcessingMatchmakingStateChanges
PFMultiplayerJoinMatchmakingTicketFromId
PFMultiplayerStartProcessingMatchmakingStateChanges
Enumerations
PFMultiplayerThreadId
PFLobbyAccessPolicy
PFLobbyDisconnectingReason
PFLobbyInviteListenerStatus
PFLobbyMemberRemovedReason
PFLobbyMembershipLock
PFLobbyOwnerMigrationPolicy
PFLobbyStateChangeType
PFMatchmakingStateChangeType
PFMatchmakingTicketStatus
Structures
PFLobbyArrangedJoinConfiguration
PFLobbyCreateConfiguration
PFLobbyDataUpdate
PFLobbyJoinConfiguration
PFLobbyMemberDataUpdate
PFLobbyMemberUpdateSummary
PFLobbySearchConfiguration
PFLobbySearchFriendsFilter
PFLobbySearchResult
PFMatchmakingMatchDetails
PFMatchmakingMatchMember
PFMatchmakingTicketConfiguration
State changes
PFLobbyAddMemberCompletedStateChange
PFLobbyCreateAndJoinLobbyCompletedStateChange
PFLobbyDisconnectedStateChange
PFLobbyDisconnectingStateChange
PFLobbyFindLobbiesCompletedStateChange
PFLobbyForceRemoveMemberCompletedStateChange
PFLobbyInviteListenerStatusChangedStateChange
PFLobbyInviteReceivedStateChange
PFLobbyJoinArrangedLobbyCompletedStateChange
PFLobbyJoinLobbyCompletedStateChange
PFLobbyLeaveLobbyCompletedStateChange
PFLobbyMemberAddedStateChange
PFLobbyMemberRemovedStateChange
PFLobbyPostUpdateCompletedStateChange
PFLobbySendInviteCompletedStateChange
PFLobbyStateChange
PFLobbyUpdatedStateChange
PFMatchmakingStateChange
PFMatchmakingTicketCompletedStateChange
PFMatchmakingTicketStatusChangedStateChange
Callbacks
PFMultiplayerAllocateMemoryCallback
PFMultiplayerFreeMemoryCallback
Typedef
PFEntityKey - Client SDK
Lobby and Matchmaking Unity API
Overview
Classes
Lobby
Properties
AccessPolicy
ConnectionString
Id
MaxMemberCount
MembershipLock
OwnerMigrationPolicy
Methods
AddMember
ForceRemoveMember
GetLobbyProperties
GetMemberProperties
GetMembers
GetSearchProperties
Leave
LeaveAllLocalUsers
PostUpdate
SendInvite
TryGetOwner
LobbyArrangedJoinConfiguration
Constructors
LobbyArrangedJoinConfiguration
Properties
AccessPolicy
MaxMemberCount
MemberProperties
OwnerMigrationPolicy
LobbyCreateConfiguration
Constructors
LobbyCreateConfiguration
Properties
AccessPolicy
LobbyProperties
MaxMemberCount
OwnerMigrationPolicy
SearchProperties
LobbyDataUpdate
Constructors
LobbyDataUpdate
Properties
AccessPolicy
LobbyProperties
MaxMemberCount
MembershipLock
NewOwner
SearchProperties
LobbyError
Constructors
LobbyError
Constants
InvalidArg
Success
Methods
FAILED
SUCCEEDED
LobbyJoinConfiguration
Constructors
LobbyJoinConfiguration
Properties
MemberProperties
LobbyMemberUpdateSummary
Properties
ConnectionStatusUpdated
Member
UpdatedMemberPropertyKeys
LobbySearchConfiguration
Constructors
LobbySearchConfiguration
Properties
ClientSearchResultCount
FilterString
FriendsFilter
SortString
LobbySearchFriendsFilter
Properties
IncludeFacebookFriends
IncludeSteamFriends
IncludeXboxFriendsToken
LobbySearchResult
Properties
ConnectionString
CurrentMemberCount
Friends
LobbyId
MaxMemberCount
OwnerEntity
SearchProperties
MatchmakingMatchDetails
Properties
LobbyArrangementString
MatchId
Members
RegionPreferences
MatchmakingTicket
Properties
Status
TicketId
Methods
Cancel
GetMatchDetails
MatchmakingTicketMatchMember
Properties
AttributesJSON
EntityKey
TeamId
PFEntityKey
Constructors
PFEntityKey
Properties
Id
Type
PlayFabMultiplayer
Constructors
PlayFabMultiplayer
Properties
IsInitialized
LogLevel
Constants
LobbyClientRequestedSearchResultCountUpperLimit
LobbyMaxLobbyPropertyCount
LobbyMaxMemberCountLowerLimit
LobbyMaxMemberCountUpperLimit
LobbyMaxMemberPropertyCount
LobbyMaxSearchPropertyCount
Events
OnAddMemberCompleted
OnError
OnForceRemoveMemberCompleted
OnLobbyCreateAndJoinCompleted
OnLobbyDisconnected
OnLobbyFindLobbiesCompleted
OnLobbyInviteListenerStatusChanged
OnLobbyInviteReceived
OnLobbyJoinArrangedLobbyCompleted
OnLobbyJoinCompleted
OnLobbyLeaveCompleted
OnLobbyMemberAdded
OnLobbyMemberRemoved
OnLobbyPostUpdateCompleted
OnLobbySendInviteCompleted
OnLobbyUpdated
OnMatchmakingTicketCompleted
OnMatchmakingTicketStatusChanged
Delegates
OnAddMemberCompletedHandler
OnErrorEventHandler
OnForceRemoveMemberCompletedHandler
OnLobbyCreateAndJoinCompletedHandler
OnLobbyDisconnectedHandler
OnLobbyFindLobbiesCompletedHandler
OnLobbyInviteListenerStatusChangedHandler
OnLobbyInviteReceivedHandler
OnLobbyJoinArrangedLobbyCompletedHandler
OnLobbyJoinCompletedHandler
OnLobbyLeaveCompletedHandler
OnLobbyMemberAddedHandler
OnLobbyMemberRemovedHandler
OnLobbyPostUpdateCompletedHandler
OnLobbySendInviteCompletedHandler
OnLobbyUpdatedHandler
OnMatchmakingTicketCompletedHandler
OnMatchmakingTicketStatusChangedHandler
Methods
CreateAndJoinLobby
CreateMatchmakingTicket
FindLobbies
GetLobbyInviteListenerStatus
Initialize
JoinArrangedLobby
JoinLobby
JoinMatchmakingTicketFromId
ProcessLobbyStateChanges
ProcessMatchmakingStateChanges
SetEntityToken
StartListeningForLobbyInvites
StopListeningForLobbyInvites
Uninitialize
PlayFabMultiplayerErrorArgs
Properties
Code
Message
PlayfabMultiplayerEventProcessor
Constructors
PlayfabMultiplayerEventProcessor
Structs
MatchUser
Constructors
MatchUser
Properties
LocalUser
LocalUserJsonAttributesJSON
Enums
LobbyAccessPolicy
LobbyDisconnectingReason
LobbyInviteListenerStatus
LobbyMemberRemovedReason
LobbyMembershipLock
LobbyOwnerMigrationPolicy
LogLevelType
MatchmakingTicketStatus
PlayStream Events
Model reference
auth_token_validated
character_consumed_item
character_created
character_inventory_item_added
character_statistic_changed
character_statistic_deleted
character_vc_item_purchased
character_virtual_currency_balance_changed
client_focus_change
client_session_start
entity_created
entity_executed_cloud_script
entity_files_set
entity_language_updated
entity_logged_in
entity_objects_set
entity_virtual_currency_balances_changed
gamelobby_ended
gamelobby_started
gameserverhost_started
gameserverhost_stopped
group_created
group_deleted
group_members_added
group_members_removed
group_role_created
group_role_deleted
group_role_members_added
group_role_members_removed
group_role_updated
group_updated
matchmaking_match_found
matchmaking_ticket_completed
matchmaking_user_ticket_completed
matchmaking_user_ticket_invite
multiplayer_server_build_deleted
multiplayer_server_build_region_status_changed
multiplayer_server_build_region_updated
multiplayer_server_certificate_deleted
multiplayer_server_certificate_uploaded
multiplayer_server_create_build_initiated
multiplayer_server_game_asset_deleted
multiplayer_server_requested
multiplayer_server_state_changed
multiplayer_server_vm_assigned
multiplayer_server_vm_remote_user_created
multiplayer_server_vm_remote_user_deleted
multiplayer_server_vm_unassignment_started
player_action_executed
player_ad_activity_valued
player_ad_campaign_attribution
player_ad_closed
player_ad_ended
player_ad_opened
display_name_filtered
player_ad_rewarded
player_ad_started
player_added_title
player_banned
player_changed_avatar
player_completed_password_reset
player_consumed_item
player_created
player_data_exported
player_device_info
player_display_name_filtered
player_displayname_changed
player_executed_cloudscript
player_inventory_item_added
player_joined_lobby
player_left_lobby
player_linked_account
player_logged_in
player_matched_with_lobby
player_profile_memberships
player_profile_subscriptions
player_paid_for_purchase
player_password_reset_link_sent
player_photon_session_authenticated
player_ranked_on_leaderboard_version
player_realmoney_purchase
player_receipt_validation
player_redeemed_coupon
player_registered_push_notifications
player_removed_title
player_reported_as_abusive
player_set_profile_property
player_started_purchase
player_statistic_changed
player_statistic_deleted
player_tag_added
player_tag_removed
player_triggered_action_executed_cloudscript
player_unlinked_account
player_updated_contact_email
player_vc_item_purchased
player_verified_contact_email
player_virtual_currency_balance_changed
sent_email
sent_push_notification
session_ended
session_started
studio_created
studio_tier_updated
studio_user_added
studio_user_invited
studio_user_removed
tenancy_connector_onboard
title_aborted_task
title_added_cloudscript
title_api_settings_changed
title_catalog_updated
title_client_rate_limited_alert
title_completed_task
title_created_task
title_deleted
title_deleted_master_player
title_deleted_task
title_exceeded_limit
title_game_build_added
title_game_build_modified
title_high_error_rate_alert
title_initiated_player_password_reset
title_limit_changed
title_news_updated
title_permission_policy_changed
title_profile_view_constraints_changed
title_published_cloudscript
title_queue_config_updated
title_requested_limit_change
title_saved_survey
title_scheduled_cloudscript_executed
title_secret_key_changed
title_started_task
title_statistic_version_changed
title_store_updated
title_updated_task
API access policy
Global API method error codes
HTTP response status codes
SDKs
Overview
Request access
Lobby and Matchmaking SDKs
Overview
C++ SDK Release notes
Unreal Engine 4
Multiplayer Unreal Online Subsystem (OSS)
OSS quickstart
Get Party libraries
Cognitive Services interface
Using older versions of Unreal Engine 4
Unreal Engine 4 Release notes
Unity
Multiplayer Unity getting started
Multiplayer Unity plugin overview
Multiplayer Unity plugin quickstart
Multiplayer Server SDKs
Party SDKs
Overview
Android getting started
iOS getting started
Unity
Party Unity plugin overview
Party Unity plugin quickstart
Party Unity plugin API reference
Party Unity plugin release notes
Unreal Engine 4
Multiplayer Unreal Online Subsystem (OSS)
OSS quickstart
Get Party libraries
Cognitive Services interface
Using older versions of Unreal Engine 4
Unreal Engine 4 Release notes
Xbox and Xbox Live
Xbox XDK prerequisites
Xbox Requirements
Use Party with MPSD
Xbox Live free program FAQ
Xbox Live Helper Library
Overview
Release notes
API reference
PlayFab SDKs
Overview
Languages
Android Studio Project (Java)
C#
Quickstart
Java
Quickstart
Objective-C
Quickstart
C++
Quickstart - Linux
Quickstart - Windows
Quickstart - Xbox One
Frameworks
Cocos2d-x
Quickstart
Phaser.io
Photon
Quickstart
Game engines
Unity3D
Quickstart
Installing the PlayFab SDK for Unity
Unreal Engine
Quickstart
scripting
ActionScript
Quickstart
Javascript
Quickstart
Lua
Quickstart - Corona
Quickstart - Defold
NodeJS
Quickstart
Python
Quickstart
Recipes and samples
General PlayFab samples
Multiplayer Servers samples
Party samples
Recipes
Tools and utilities
SDK Generator
Quickstart
Postman
Quickstart
What is PlayFab?
5/24/2022 • 5 minutes to read • Edit Online

PlayFab is a complete backend platform for live games with managed game services, real-time analytics, and
LiveOps. Boost your revenue and increase player engagement while cutting costs. This topic provides a high-
level overview of the PlayFab features.
PlayFab's backend services reduce the barriers to launch for game developers, offering both large and small
studios cost-effective development solutions that scale with their games and help them engage, retain and
monetize players. PlayFab enables developers to use the intelligent cloud to build and operate games, analyze
gaming data and improve overall gaming experiences. The PlayFab platform is a natural complement to Azure
for gaming (Visit azure.com/gaming for more info). Azure, with locations in 42 regions worldwide, provides
world-class server infrastructure, allowing creators to focus on building great games with best-available global
reach. For gamers, this leads to a higher, faster degree of innovation and better experiences.
Using PlayFab you can:
Remove the challenges of building, managing, and running servers at scale with a complete back-end
solution.
Instantly scale dedicated multiplayer servers that deliver low latency and high reliability for real-time
gameplay.
Use multiple forms of built-in authentication to track players across devices.
Quickly create leaderboards to more deeply engage players.
Accelerate growth with economy services that let you create and track virtual currencies, manage stores of
items, and process payments.
To use PlayFab features, you must sign up for a PlayFab account.
PlayFab provides the following services:

Multiplayer Services
Cross-Network Identity and Data
Player Authentication : Start with frictionless authentication and let players link accounts to roam across
Windows, Xbox, Steam, PSN, Nintendo, Facebook, iOS, Android and more.
Player Data Management : Share player information and game state across devices.
Matchmaking - Use the proven capabilities of Xbox Live's SmartMatch on any platform to help players find
opponents.
Multiplayer Servers
Dedicated Ser vers : Deliver low-latency real-time gameplay for any platform.
24/7 Monitoring and DDoS Protection - Protect against DDoS attacks and other incidents.
Global Reach with Microsoft Azure : Get closer to players on a cloud with more global regions than any
other provider.
Control Costs : Dynamically scale server cores in response to demand.
Chat
Par ty : Connect players with low-latency peer-to-peer communication.
Text and Voice Chat : Facilitate accessible voice chat, transcription and translation.
Accessibility : Use automated speech-to-text transcription and voice synthesis to make communication simple
for everyone.
Real-Time Translation : Break down global barriers and grow player concurrency by translating voice and text
chat between more than 30 different languages.
Encr yption : Ensure secure player communications.
Leaderboards and Statistics
Tournaments and Leaderboards : Facilitate permanent or time-limited competitions amongst friends or
strangers.
Scheduling : Reset leaderboards on a schedule and archive standings so players can view past results.
Prizes : Reward players based on their actions and leaderboard ranks.
Cheat Prevention : Defend against unwanted behavior and remove fraudulent players and accounts.

LiveOps
Engagement and Retention
Game Manager Web Por tal : A shared space (with roles and access permissions) where studio members can
build, configure and operate your game.
Daily Repor ts : Evaluate your game's performance through the lens of the top metrics used across the industry,
pre-calculated for you daily.
Player Profiles : Track players across authentication services and platforms.
Customization : Use server-hosted player data and logic to build custom game mechanics.
Achievement Systems : Use the rule engine and custom player events to build a powerful achievements
system.
Real-Time Segmentation : Act immediately on targeted groups of players.
Player Communication : Talk to your community with push notifications, emails, and message-of-the-day pop-
ups.
Content Management
Title Data : - Manage your game configuration remotely.
Item Catalog : Configure your catalog of items available for in-app granting or purchase, and update at any
time.
Content Deliver y Network : Upload, host and deliver game assets via Game Manager.
A/B Testing
Player Buckets : Run experiments with randomly assigned groups of players.
Monetization
Stores and Sales : Target player segments with personalized store offers and support payments with Xbox,
Steam, Google, PayPal and more.
Vir tual Economy : Mint promotional coupons and virtual currencies with support for setting initial balances
and optional auto-recharge.
User Generated Content : Empower players to create, upload and search for moderated content.
Drop Tables : Craft attractive bundles for first-time or regular users and stimulate demand with item scarcity.
Fraud Prevention : Use server-side receipt validation to make sure purchases are genuine before completion.
Automation
CloudScript : Build lightweight logic processing when you want server authority without a dedicated server.
Task Scheduling : Set up pre-defined actions to manage anything from prices and events to messaging lapsed
players.

Data and Analytics


Real-Time Analytics
PlayStream : Monitor a unified real-time stream (and historical archive) of every event fired by your game.
Real-Time Rules Engine : Set up powerful actions and triggers that respond to PlayStream events.
Real-Time Segmentation : Use data properties to bucket players into segments and trigger actions as they
enter or exit.
Event Filter and Search : Zoom in on a time slice to analyze players, events and error conditions in detail.
Repor ts : Review summaries of your game's daily and monthly performance with automatic reports available by
daily email and on-demand.
Data Management
Insights : Gather all event and processed data into a single title database in the cloud.
Event Archiving : Schedule event exports to a pre-existing Azure Blob Storage or Amazon S3 data warehouse.
Compliance
GDPR : PlayFab is committed to being General Data Protection Regulation (GDPR) compliant and as your service
provider, ensuring that we provide you with the hooks you need to allow players to view or delete their data.
COPPA : PlayFab is in use today by COPPA compliant games.

SDKs
SDKs are available for most popular engines and platforms.
Supported Languages
Android Studio (Java)
C#
Java
Objective-C (iOS)
PlayFab CPP (C++)
Frameworks
Cocos2D
Phaser.io (JavaScript)
Game Engines
Lua
Unity3D
Unreal Engine (Blueprints & C++)
Scripting
ActionScript
JavaScript
NodeJS
PHP
Python

Support
Documentation : Get started quickly with tutorials, samples, and comprehensive reference documentation.
Forums : Learn from experts and share your knowledge in the community forums.
Slack : Join channels for ongoing conversations with other developers and direct communication with PlayFab
Developer Success.
Real-Time Ser vice Health : Visit status.playfab.com for current and historical service health information.
Tickets : Get enterprise-level ticketed support.
24/7 Emergency Escalations : Get around-the-clock assistance on immediate-priority issues.
Game Manager overview
5/24/2022 • 2 minutes to read • Edit Online

This article introduces Game Manager, the PlayFab developer portal, identifies portal page elements, and helps
you get familiar with the portal experience.

What is the Game Manager?


The Game Manager is a web-based, dashboard that provides access to your studios and tools to manage your
Titles. It is your go-to destination for managing your studio and title configuration. Most of the tutorials across
PlayFab will reference how to accomplish tasks both in Game Manager and through API calls.
PlayFab’s Game Manager provides a fully integrated backend suite that puts you in the driver seat and gives you
the option to pick and choose the services that work best for your game.
Use Game Manager to invite teammates to collaborate with you, grant them full or partial access to make
changes, configure and manage secret keys, make encryption related settings, and set how much you want to
trust your client app.

About the Game Manager interface


When you log in to Game Manager, you are presented with the My Studios and Titles page which lists all of
the Studios and Title to which you have access. Select a Title to manage it.
Management of a Title is divided into four major views:
Title Overview - Review of the recent and overarching performance of your Title.
Build - Foundational elements and tools to configure your game.
Engage - Facilitate connections with players.
Analyze - Monitor and act on player behaviors.

Next steps
Game Manager quickstart - Sign up for a PlayFab account, create your studio, and your first game.
Game Manager reference - Learn about the functionality available Game Manager.
Quickstart: Game Manager
5/24/2022 • 2 minutes to read • Edit Online

Get started with PlayFab by using Game Manager to create your PlayFab account, create your Studio, and create
your first Title.

Create a PlayFab account


On the PlayFab sign up screen, you can create a PlayFab specific account or use your Microsoft account to sign
in.
When you have signed in, PlayFab prompts you enter your contact information and studio information. If you
have not finalized the game studio name, you can change it later.

Create your first game


To create a game, you must, at a minimum, enter a name for the game. You can also specify additional details
about your Title, such as the Title genre, monetization mode, target marketplaces, and player mode. The
Benchmark comparisons feature uses these properties to display a finer grained view of benchmark data. You
can set these options at a later time.

Your studios and Titles


When you have successfully created your account, studio, and first game, Game Manager opens in the
dashboard for your Title.
The next time you log in, Game Manager opens the My Studios and Titles page. From there, you can select a
Title to open its dashboard. For a detailed introduction to the features of Game Manager, see Game Manager
reference.
Many API calls require a TitleId, which is the string ID found beneath the title of your game. In the following
dashboard, the title is "My Game" and TitleId is "F71AC."
Next steps
PlayFab User Roles
Getting started for developers
Game Manager reference
5/24/2022 • 12 minutes to read • Edit Online

This reference familiarizes you with the high-level aspects of the Game Manager. For more detailed information,
you may select your specific topic of interest in the PlayFab documentation that follows.
To get the most value from this topic, you should have created your PlayFab account, logged in, and viewed the
Game Manager for your title, even if it's an empty title for now.
The sections provided below offer greater insight on each Game Manager area. Each time you perform an API
call or task, view the results in the Game Manager in the appropriate area for that task.

About Game Manager


Select a title from My Studios and Titles to follow along.
Game Manager is split into four major sections:
Title Overview – Review recent and overarching performance of your Title.
Build – Foundational elements and tools to configure your game.
Engage – Facilitate connections with players.
Analyze – Monitor and act on player behaviors.

Title Overview
An overview of the recent and less-recent performance of your title.
Over view - shows your game's basic statistics and what you may have assigned as Key Performance Indicators
(KPIs). In the upper-right, you will find time period toggle buttons, and there are also filters for the tables.
4h : This will load data generated within the last 4 hours.
24h : This will load data generated within the last 24 hours.
3d : This will load data generated within the last 3 days.
7d : This will load data generated within the last 7 days.
mtd : This will load data generated within the current month.

NOTE
In Game Manager, all times are displayed in local time.
The tables in the Overview tab allow you to monitor PlayStream events in real time. They include the following:
Unique Users : The average number of unique players logging in per day.
API Calls : Indicates how many API calls were executed within the given time period.
CloudScript Processing Times : Provides the average processing time for your CloudScript functions to
execute.
LOGINS : The number of logins recorded for the selected time span.
NEW USERS : New users added in the time period.
PURCHASES : The USD value of real money transactions processed for the selected time span.
REPORTS : The Reports table consolidates several critical categories into a useful format. Specific reports are
also available under the Repor ts tab in Analytics.
Back to About the Game Manager
PlayStream Monitor - PlayStream is our latest and greatest addition to the PlayFab platform. It displays title
events as they are generated in real time, and you can visualize them at whatever granularity you prefer on the
world map. Use the sampling controls to gather more or less events per second.

Back to About the Game Manager

Build
Provides the foundational elements and tools to configure your game.
Players
Players contains settings and data pertaining to your individual players, including player segmentation.
In this section of the Game Manager, a sorted list is presented, and organized by most recent login. Select any of
the records to display the Player's Overview. Use the Search box to search for players by ID , Username ,
Display Name , or Email .

Over view - this detailed screen provides a wealth of insight into the players' activities. The sub-menu contains
many links to other player-centric information, as shown below.

Some specific tools your team can use to remedy defrauded players and identify potential abusers are included
below.
Over view - View basic details and linked account status.
CloudScript - View and run CloudScript functions.
Multiplayer - View player match history from multiplayer sessions.
PlayStream - View player generated events.
Purchases - View a player's real money purchase history.
Statistics - View and edit player statistics.
Logins - View player login history.
Bans - View player ban history.
Characters - View player-owned characters and edit basic details.
Player Data - View and edit player data records.
Segments - View which segments a player has entered.
Multiplayer
Multiplayer allows you to configure server hosting and matchmaking.
Ser vers - Whether you are looking to hosting multi-player matches or just need a secure environment that can
reduce many common forms of hacking and abuse, the PlayFab Thunderhead servers work with many
architectures and game types. These servers provide an excellent alternative when compared with the overhead
of dedicated game servers.
Matchmaking - Set up your matchmaking queues by configuring match sizes, servers and statistics.

Par ty - Create and configure the Parties for your title.

NOTE
You must be an Indie, Pro, or Enterprise subscriber in order to enable Parties.

Legacy Multiplayer - Here you can see your active and archived games, as well as server activity, game builds,
and game modes.
Additional information:
CloudScript Quickstart
Back to About the Game Manager
Groups
The Groups section allows you to create and manage groups of players designated by entity type and ID.
Automation
In the Automation area, you can run CloudScript, run A/B tests, assign Rules, and schedule tasks for your game
title using server-side logic for your game, including scripting, rules, and tasks. Configure and trigger actions
based on events generated by your title.
Add-ons
The control center for managing partner integrations.
To configure marketplace integrations for your title: Explore the Add-ons section of the Game Manager for
details on the various add-ons.

Setup instructions for each add-on may vary. Additional billing information may also be required.
Back to About the Game Manager

Engage
Engage allows you to facilitate connections with players.
Economy
This section provides all the tools needed to manage the virtual economy of your game.
Catalogs - At the center of PlayFab economies is the concept of catalogs. Catalogs are a collection of items,
stores, and drop tables.
As an example, the following image shows the primary catalogs for Unicorn Battle .

Items - An item within the catalog. Items can be of several different types.
Drop Tables - Control the item distribution when players open containers and bundles.
Stores - A subset of catalog items that can be set to prices that are different than those specified by the catalog.

NOTE
Select any catalog item to open a detailed editor for the properties of the item.

Currency - Trackers for each currency that can be exchanged for catalog items.
The following example shows the Edit Currency page for Great Game .
Additional Information:
Catalogs Tutorial
Currencies Tutorial
Back to About the Game Manager
User Generated Content
The User Generated Content tab displays all published content for your title. When enabled, all users can create,
discover, and consume content.

UGC Items - An item within the public catalog. UGC Items can be created by a player, by a title, or on behalf of a
player (by a title). UGC Items can contain Files and Images that can be downloaded by another player.
Settings - You can configure supported metadata values here (like Content Types and Tags), and specify specific
player IDs to receive elevated permissions (to assist with moderation scenarios).

Policies - Policies allow you to control the client access to the Economy APIs.
Additional Information:
UGC Overview
UGC Quickstart
Back to About the Game Manager
Leaderboards
The Leaderboards tab displays all the active leaderboards for your title. PlayFab leaderboards are driven by the
statistics you choose to use for your players. You can also configure the reset frequency and aggregation
method.

Within a leaderboard, select a Player Name to see the player overview.


Select the orange EDIT LEADERBOARD button to edit your leaderboard name as well as the reset frequency.
Prize Tables - Allows you to create and manage prize tables associated with specific leaderboards. Various
items can be configured to be sent to players in the leaderboards, depending on how it is set up.
Additional information :
Using resettable statistics and leaderboards
Back to About the Game Manager
Content
The Content section offers tools for engaging with your players. The content can include news, remote
configuration, and files.
Title Data - Here you can configure and store key properties which you can change after your game launches.
Title data is accessible from all API sets by all users. Because of this, title data is an ideal place to store your
custom title settings. Internal data is hidden from game clients and only available on your game servers.
Add or edit title data keys
1. Enter text for your Key (keys must be unique.
2. Enter text for your Value (accepts strings up to 10KB).
3. Save your changes with the orange SAVE TITLE DATA button under the data table.

Remove title data keys


1. Check the box that corresponds to the row(s) that you wish to remove.
2. Select the X Remove link in the top-left, above the User table.
3. Save your changes with the orange SAVE TITLE DATA button under the data table.
Title News - Create title news for your game title. As needed, add additional languages.
File Management - Create, organize and upload files for your game client via the Content Delivery Network
(CDN).

NOTE
There are varying time delays, depending on the type of file handling that is required. For detailed information, view the
online Help for the File Management tab.

Email Templates - Create, configure and manage email templates for game clients.
The following example shows the Email Templates tab for Great Game.
Back to About the Game Manager
Push Notifications Templates - create and manage new Push Notification templates.

Analyze
Analyze allows you to monitor and act on player behaviors.
Dashboards
Dashboards allow you to see Trends, run Reports and perform Diagnostics.
Data
In the Data area you can do a number of things to track and analyze data from your players' activities. There are
a number of graphing and reports capabilities that provide the ability to consolidate and visualize the data.
Trends - Configure and view trends for a number of statistics for time periods ranging from 7 days to 26
months. The Trends graph shows classic retention - only new players that have returned - for the chosen time
period. The 30-day retention report includes both new and returning players. Event Histor y - Search and
display a number of different Event History types, depending on the query you create. Use event name, date
range, or event values. Repor ts - Use Reports to view and download a number of different types of reports
based on player data and statistical values.

For additional or custom reports, please open a feature request in our community forums.
Webhooks - Webhooks allow you to have some or all of your PlayStream events forwarded to any web URL
you want. The event data is sent via POST in the request body as JSON.
Back to About the Game Manager

About Audit History and Billing


Every action taken within the Game Manager is logged in the Audit History log.
To display the Audit History, select Title audit histor y from the Settings menu for your game title.

On the Audit History page, select any entry in the log to view the complete details. You can also navigate
through the Logs using the SEARCH button.
The Event time column exposes information about the time and the author of the change.
The Log type column gives you a clue about the kind of change that was made.
The String change and Value columns represent short details of the change.
The View column allows you to access a full JSON description of the change.
Billing - On the Billing page you can view your Contact Information and Credit Card information which PlayFab
invoicing references for payment.

About title settings


Access the title settings from the Settings menu.
General - Provides basic information that you will use to configure your title such as player display names and
the default language for your title.
API Features - Allows you to configure the API aspects of your title. By default, all options are unchecked, and
therefore, not enabled. Enabling these features allows your title to be client-authoritative at the expense of
security.

Choose your preferred options, and select the Save button.


Secret Keys - Allows you to create and manage your PlayFab secret keys, the unique identifier for your game
when making Admin and server API calls.

IMPORTANT
This key should only be shared with trusted members of your development team, since it enables API calls that can affect
game data and player accounts. Never share your PlayFab API secret key with anyone; doing so may jeopardize your title's
security.

Email Preferences - Allows you to configure e-mail settings such as Subscription and Reply-To addresses.
Push Notifications - Configure notifications to be sent to android or iOS devices. Limits - Set limits on certain
PlayFab features, economic or otherwise in your game. Client Profile Options - Allows you to configure what
a Client can or cannot access and configure on their own for the title.

Other basic actions


Edit profile settings
1. From the drop-down menu in the upper-right corner of the Game Manager window, select My Profile .
2. Specify Your Name , a Password , add a Phone number , set your Time zone , and specify whether you
want to enable Two-Factor Authentication .
3. Select the Save Profile button to save your changes and return to the studios page.

NOTE
Two-factor authentication improves the security of your developer accounts by requiring a code to be supplied when
logging in.

View PlayFab news


New notifications will be indicated in the little bell icon in the upper-right corner of your window.
1. Select icon to display News .
2. View the news from the PlayFab team, ordered by the most recent, first. The news feeds include information
on new features, API updates, and service outages.
Create and edit studios and titles
In this section you learn how to create and manage studios and game titles.
To add a new studio:
1. Click the PlayFab icon to display the My Studios and Titles pages.
2. Click NEW STUDIO to create a new studio in the dialog that appears.
3. Enter a Studio Name and Authentication provider .
4. Save your changes and return to the My Studios and Titles page.
To edit an existing studio:
1. Select the elipsis drop-down menu to the right side of your Studio name , then select Studio settings .

2. Make your edits.


3. Select Save Studio to return to the My Studios and Titles page.
To add a new title:
1. Select the drop-down menu to the right side of your Studio's Name, and then select New title to display the
Create Title page.
2. Enter the details and click the CREATE TITLE button.

3. Save your changes and return to the My Studios and Titles page.
To edit an existing title
1. Select the gear icon on the title name you wish to edit and select Edit title info .

2. Make your edits.


3. Save your changes and return to the My Studios and Titles page.
About User Accounts
You can create user accounts that are individual or Admin-level accounts. Admin accounts provide access to one
or more sections on one or more titles of a given studio, and of course provide full ability to configure studio
and title information.
1. Select the drop-down menu to the far right from your Studio name, and then select Studio users .
2. Choose ADD USER to display the Add New User page. Check the box if you want to make the user an
Admin.
3. To remove accounts in the Users page, simply select Remove .
If you do not already have a PlayFab Admin account, an e-mail will be sent to the address you provided. Upon
confirmation, the new account will have access to the Studio and title.
Creating a PlayFab account
5/24/2022 • 2 minutes to read • Edit Online

Before you can call any PlayFab API, you must have a PlayFab developer account. If you already have a PlayFab
account, you can skip this step.

Once you have a PlayFab account, navigate to the PlayFab home page, https://playfab.com, and log in.
Since PlayFab does not know the name of your game studio or the title of your game, when you create a studio,
a placeholder title called My Game is created for you. You can edit your title's information in the Create Title
screen at any time.

NOTE
The Title ID is unique to your game, which we refer to as a title. You will use this value when you make PlayFab API calls
(your Title ID will not be BCFE ).
Your first title is automatically generated by us. To create a new title, select New title from the Elipsis menu.

Open the Game Manager for your title


Before installing any SDK, select a game title, and the Game Manager will open. Take the time to familiarize
yourself with the various sections in the Game Manager dashboard.
For a more detailed overview, visit the Game Manager quickstart.
The PlayFab Game Manager allows you to do whatever you need to with your game title. Once you have a grasp
on the aspects of the Game Manager, install the SDK so you can start using APIs. for more information on how
to do this, see Getting Started for Developers.
API feature settings in the PlayFab Game Manager
5/24/2022 • 3 minutes to read • Edit Online

The API features in the PlayFab Game Manager are a handful of options for managing the behavior of PlayFab
APIs for your title. These options give you the tools for managing access, privacy, and other features.
To find the screen for configuring these options:
Go to the Game Manager .
Select Settings from the menu to your left.
Select the API Features tab.

Some of these check boxes are obvious, while some are not. In this tutorial, we will go into detail about several
of them.
NOTE
Several screenshots and demonstrations in this tutorial utilize Postman.

Requiring valid JSON for custom data values


Hacked clients can cause some serious problems for games. Rogue API callers posting badly formatted data can
produce noise, bugs, and issues for developers. Players who have poorly formatted data will often require
manual intervention for clean up.
Requiring valid JSON for custom data values will perform basic content type validation before data is saved to
the database. Catching these problems early prevents these issues from lingering on, and stops hackers from
interfering with normal development.
When this flag is set, it forces clients to pass in valid JSON for each key of their custom data. Simple JSON
validation by itself won't prevent all issues - but can help weed out some bad behavior.
Checking this option will require that each key saved across all custom data, including player, publisher,
character, title, and item data must be valid JSON.

NOTE
This flag can be toggled on or off at any time. But, it's not retroactive. So existing values will not be affected. Only newly
written values will be validated.

If you attempt to pass invalid JSON as a value, it will reject the request with an
HTTP Status Code 400 "Bad Request" .
Disabling all API request access
Surprisingly, it can be useful to disable all API access to your titles.
If, for example, you are performing a sensitive migration with downtime, stray API requests could cause serious
interruptions. If you are retiring your game, this will guarantee your game really is off.

WARNING
Keep in mind, that marking this checkbox will literally break your game , so use it with caution!

Once you have decided you need to turn API access off, and you check the box, all API requests will begin to fail
within a few minutes.
PlayFab will return an HTTP Status Code 400 "Bad Request" , indicating that the title has disabled such usage.
These HTTP Status Code 400 responses will persist until you un-check the box. Again, un-checking may take a
few minutes to have effect.

Enabling player IP address obfuscation


For many studios, owning Personally Identifiable Information (PII ) is a liability best avoided. One common
(and useful) form of PII is IP Address .
IP Address is useful for a handful of reasons, including geo-location. However, the full accuracy of the IP is often
considered PII.
PlayFab can help limit this is by obfuscating parts of the IP addresses. Now, by checking a box, you can stop
gathering this sensitive data.
After you check this box, PlayFab will always record 0 for the last octet of a player's IP. You can verify this is
working by checking the login history for players in the Players tab.
You should see that every IP ends in .0 . Any IPs that were recorded before IP address obfuscation was enabled
will retain their full detail. So if your game is PII-sensitive, set this checkbox before you launch.

NOTE
Enabling obfuscation will impact other features that use the IP address. In particular, IP-based geo-location and player
bans by IP are the two most directly impacted.

PlayFab automatically performs IP-based geo-location on logins. This helps you automatically determine where
on earth your players come from.
However, you may experience reduced accuracy, particularly at the city level, when using obfuscated IPs. This is
intentional, as the goal of obfuscating IPs is to avoid recording PII, including exact locations.
Additionally, obfuscating IPs can affect bans. When adding a ban, you can optionally ban an IP as well. Often
banning by IP is more practical than banning one account at a time, because the bad actor can just make new
accounts.
Banning an IP prevents the bad actor from making new accounts from the same internet connection. In many
cases, this is an effective tool.
However, with obfuscated IPs, banning an exact IP cannot work. Instead, you must use a ban on an IP with .0 as
the final octet.

Please keep in mind this will effectively ban an entire IP range.


This will still ban the bad actor, but other innocent players with similar IP addresses may be affected.
Furthermore, existing precise IP bans will cease to be effective.
Audit logs
5/24/2022 • 2 minutes to read • Edit Online

Audit logs allow you to observe and analyze the history of important changes made to your title by you or other
developers. You are able to detect both important changes and destructive actions, and react accordingly.

Accessing audit logs


On the Audit Histor y page, select any entry in the log to view the complete details. You can also navigate
through the Logs using the SEARCH button.
The Event time column exposes information about the time and the author of the change.
The Log type column gives you a clue about the kind of change that was made.
The String change and Value columns represent short details of the change.
The View column allows you to access a full JSON description of the change.

The View column displays a button to access the JSON body of the change. JSON is displayed in a modal
window.
It contains:
1. The same data as the table.
2. Plus a raw JSON body specific for each change type.
Encrypted logins
5/24/2022 • 4 minutes to read • Edit Online

PlayFab allows you to reinforce application security by protecting certain client API calls with custom encryption.
This tutorial shows you how to enable encryption for your client.
The method we will be using allows you to protect any login API call. Since the process is always similar, we only
show how to protect one particular method, LoginWithCustomID .

IMPORTANT
Login encryption is meant to be used for all players after title creation, or not at all. This is not a feature that can be
enabled at a later date. You must use it from the very beginning or not at all. In particular, encrypted players will never be
able to log in un-encrypted, and non-encrypted players will never be able to become encrypted players.

In this guide we will:


1. Create a player-shared secret.
2. Introduce an API Policy rule to enable protection on a certain method.
3. Change the client to use a player-shared key to retrieve the public title key and encrypt the payload.

NOTE
PlayFab makes the following disclaimer: "All of our API calls are already safely encrypted to modern standards, and the
standard API call encryption is everything most customers will need. This feature represents an additional layer of security
built around making it harder for players to use an unauthorized client. It is not foolproof - it merely increases the
difficulty bar for hackers. For most developers, the mild security increase will not be worth the extra effort required."

Creating a player-shared secret


The PlayFab Admin API exposes a method to manage your player-shared secrets.

NOTE
Creating a new shared secret by a certain name will override the existing key with the same name, if any. In addition, you
may have several shared secrets registered under different names.

Run the following code to add a player-shared secret to your title.


PlayFabSettings.staticSettings.DeveloperSecretKey = "__DEVELOPER_KEY__";
PlayFabSettings.staticSettings.TitleId = "__TITLE_ID__";
var response = await PlayFabAdminAPI.CreatePlayerSharedSecretAsync(new CreatePlayerSharedSecretRequest()
{
FriendlyName = "__KEY_NAME__"
});

if (response.Error != null)
{
Console.WriteLine(response.Error.GenerateErrorReport());
}
else
{
Console.WriteLine(response.Result.SecretKey);
}

To run this code, you need a developer secret key. For more information about secret keys, see Secret key
management.
This application should print a newly created player-shared secret. Make sure to save it. If it is lost, you will have
to generate a new secret by running the application again.
The secret looks like this:
QC953WQ3TU6ZJTZMAT1FNJQIKR92FPUQTISW4Q6WD8SY841MQQ

Updating the policy


We have a new shared secret created. Now we need to tell PlayFab which API calls to protect.
Run the code shown below to protect the LoginWithCustomId API call, and unprotect the rest of the API calls.
// Set development key and title id
PlayFabSettings.DeveloperSecretKey = "__DEVELOPER_KEY__";
PlayFabSettings.TitleId = "__TITLE_ID__";

public static async Task SetApiPermission(bool restrictCustomId)


{
// The first statement denies every call to LoginWithCustomID that is not properly encrypted
var filterCustom = new PermissionStatement
{
// Statement effects any action
Action = "*",
// Filter the case where there is no signature and payload is not encrypted
ApiConditions = new ApiCondition()
{
HasSignatureOrEncryption = Conditionals.False
},
Comment = "Deny every request to LoginWithCustomID that is not properly encrypted",
// Specify the resource name
Resource = "pfrn:api--/Client/LoginWithCustomID", // Resource name
// Deny any of such requests
Effect = EffectType.Deny,
// For any user
Principal = "*"
};
// The second statement allows every other API call
var filterNothing = new PermissionStatement()
{
// Statement effects any action
Action = "*",
Comment = "Allow the rest API calls",
// For any resource name
Resource = "pfrn:api--*",
// Allow any request
Effect = EffectType.Allow,
// For any user
Principal = "*"
};

// Update the policy


var request = new UpdatePolicyRequest()
{
// ApiPolicy controls access to API methods
PolicyName = "ApiPolicy",
// In this example we overwrite the policy. Consider appending to the existing policy instead.
OverwritePolicy = true,
// Introduce policy statements
Statements = new List<PermissionStatement> { filterNothing }
};
if (restrictCustomId)
request.Statements.Add(filterCustom);
var result = await PlayFabAdminAPI.UpdatePolicyAsync(request);

// Handle possible errors


if (result.Error != null)
Console.WriteLine(result.Error.GenerateErrorReport());
else
Console.WriteLine("Policy updated");
}

Setting up the client


Now when the policy is updated, you are no longer able to just call LoginWithCustomID API. Consider the code
shown below.
var result = await PlayFabClientAPI.LoginWithCustomIDAsync(new LoginWithCustomIDRequest()
{
CreateAccount = true,
CustomId = "Some_Custom_Id"
});

if (result.Error != null)
{
Console.WriteLine(result.Error.GenerateErrorReport());
}
else
{
Console.WriteLine(result.Result.PlayFabId);
}

Normally, this would log in the user without a problem. However, now this API call is protected - and the code
will yield a Not Authorized error (not to be confused with Not Authenticated ).
We need to modify the client to properly encrypt the call payload. This is done in 2 steps:
1. Use the player-shared secret to fetch the title public key.
2. Use the title public key to encrypt the payload.
The code shown below illustrates this.
public static async Task DoEncryptedLogin()
{
Console.WriteLine("Begin DoEncryptedLogin");

// Use Player Shared Secret to get Title Public Key


var titleKeyResult = await PlayFabClientAPI.GetTitlePublicKeyAsync(new GetTitlePublicKeyRequest
{
TitleId = TITLE_ID,
TitleSharedSecret = CLIENT_SECRET_KEY
});

Console.WriteLine("Encrypt request");
// Convert public key to bytes
var cspBlob = Convert.FromBase64String(titleKeyResult.Result.RSAPublicKey);

// Serialize certain part of the model into string (this will be encrypted).
var encryptionModel = JsonWrapper.SerializeObject(new LoginWithCustomIDRequest { CustomId =
"SOME_PLAYER_ID_ENCRYPTED" });
string encryptedPayload;

// RSA encryption
using (var rsa = new RSACryptoServiceProvider())
{
rsa.ImportCspBlob(cspBlob);
var bytesToEncrypt = Encoding.UTF8.GetBytes(encryptionModel);
var encryptedBytes = rsa.Encrypt(bytesToEncrypt, false);
encryptedPayload = Convert.ToBase64String(encryptedBytes);
}

// Use encrypted payload to construct a model


var model = new LoginWithCustomIDRequest
{
EncryptedRequest = encryptedPayload,
PlayerSecret = CLIENT_SECRET_KEY,
CreateAccount = true
};

Console.WriteLine("Call LoginWithCustomIDAsync");
// Finally execute the call
var result = await PlayFabClientAPI.LoginWithCustomIDAsync(model);
Console.WriteLine("LoginWithCustomIDAsync done");
bool successful = result.Error == null && result.Result != null;
if (!successful)
Console.WriteLine(result.Error.GenerateErrorReport());
else
Console.WriteLine("Login Successful" + result.Result.PlayFabId);
}

Once you run the code, you should be able to log in. Keep in mind that once a player-shared secret is created, it
must be hard coded into your client code, as there is no way to fetch or request it by using any API call.
Player encryption services
5/24/2022 • 3 minutes to read • Edit Online

Player shared secrets


Player shared secrets is a new type of pseudo-secret key, which is shared amongst game clients. Using an API, it
can be traded for the public RSA key of the title, and can be used to perform account registration.
Titles can have multiple player shared keys, and can set them up and revoke them at will, via the Admin API calls
Create, Update, Delete, List.
Player shared secrets should be baked into the respective clients, as there are no client APIs to retrieve them -
either authenticated or otherwise.

Title public key


The player shared secret is then sent to GetTitlePublicKey which - if the key is valid - will return a Base 64
encoded RSA CSP blob byte array that can encrypt 237 bytes of data.
All APIs that allow accounts to be created, now accept posting a registration request as an encrypted payload to
the EncryptedRequest field.

NOTE
The standard fields TitleId , InfoRequestParameters and CreateAccount should not be included in the encrypted
payload.

Using title public key to register


Here is example code to register a player using LoginWithCustomID and the title public key.
var titleKeyResult = PlayFabClientAPI.GetTitlePublicKey(new GetTitlePublicKeyRequest{ TitleId = "TITLE",
TitleSharedSecret = "player shared secret" });

var cspBlob = Convert.FromBase64String(titleKeyResult.RSAPublicKey);

var encryptionModel = JsonConvert.SearializeObject(new LoginWithCustomIDRequest

{
CustomID = "my player's custom id",
PlayerSecret = "my player's individual secret"
});

string encryptedPayload;

using (var rsa = new RSACryptoServiceProvider())


{
rsa.ImportCspBlob(cspBlob);
var bytesToEncrypt = Encoding.UTF8.GetBytes(encryptionModel);
var encryptedBytes = rsa.Encrypt(bytesToEncrypt, false);
encryptedPayload = Convert.ToBase64String(encryptedBytes);
}

var postModel = new LoginWithCustomIDRequest


{
TitleId = "TITLEID",
EncryptedRequest = encryptedPayload,
CreateAccount = True
};

var createAccountResult = PlayFabClientAPI.LoginWithCustomID(postModel);

Player secret
A part of the new registration system is a new field called PlayerSecret . If set, it allows you to sign request
headers that will be validated by the server during API calls to all services, including Login Requests.
The player secret can only be set once per user per title (a user with multiple titles in the same studio will need
to set the player secret for each one).
If the player secret isn't set during registration, it is possible to set it (if it is not already set) by calling
SetPlayerSecret. There are admin and server APIs that allow setting the player secret to a new value even if it
has previously been set.

NOTE
Once set, the player secret should be stored securely on the device, as it is not recoverable if lost, and no APIs exist to
recover it.

Using player secret to sign API requests


The following code example constructs a signature header that can be used to sign API requests. The format for
the signature header is shown below.
jsonRequestModel.utcTimeStampInISO.playerSecret
var postModel = new LoginWithCustomIDRequest

{
TitleId = "TITLEID",
CustomID = "my player's custom id",
CreateAccount = False
};

string signatureHeader;
string timestampHeader = DateTime.UtcNow.ToString("O");

string playerSecret; // the player secret that was sent during registration.

using (var hash = new SHA256Managed())


{
var bytesToHash = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(postModel)+"." + timestampHeader +
"." + playerSecret);
signatureHeader = hash.ComputeHash(bytesToHash);
}

var customHeaders = new Dictionary<string, string>


{
{ "X-PlayFab-Signature", signatureHeader },
{ "X-PlayFab-Timestamp", timestampHeader }
}

var loginResult = PLayFabClientAPI.LoginWithCustomID(postModel, customHeaders);

Using a policy enforcement


API Policies can now be used to enforce either:
That a client request is an encrypted payload.
That a client request contains signed headers.
Even without using the policy enforcement, if an encrypted payload is sent (or the headers are sent), they will be
validated and an error will occur if they are not properly formed.
To create a policy to require headers on a specific API, use a Deny statement. This creates a policy requiring
headers on all calls you can place that aren't permitted by the Allow statement.
Policy statements have a property called ApiConditions . ApiConditions contains a property called
HasSignatureOrEncryption , which is an enum with three possible values:

Any
True
False

NOTE
The default (if it is not set by the policy), is Any .

The following example policy will allow all API calls (except un-encrypted or missing header calls) to
LoginWithCustomID .
{
"PolicyName": "ApiPolicy",
"OverwritePolicy": true,
"Statements":
[
{
"Comment": "Require Headers on LoginWithCustomID",
"Action": "*",
"Principal": "*",
"Effect": "Deny",
"Resource": "pfrn:api--/Client/LoginWithCustomID",
"ApiConditions": { "HasSignatureOrEncryption": "False" }
},
{
"Comment": "Allow the rest policy",
"Action": "*",
"Principal": "*",
"Effect": "Allow",
"Resource": "pfrn:api--*"
}
]
}

Because the Deny statement is HasSignatureOrEncryption False , those requests that do not match it will be
rejected.
However, requests that have signature headers or encryption will be allowed by the Allow the rest policy .
PlayFab user roles
5/24/2022 • 4 minutes to read • Edit Online

PlayFab now supports roles as a more efficient way to manage user permissions within the Game Manager.
We're very pleased to have added this feature, since it's been one of the most frequently requested features.
With the introduction of roles, we are phasing out the ability to directly edit user permissions. This is no problem
for new titles - those can immediately begin using the new roles system.
However, existing titles that are using custom permissions must first migrate these custom permissions over to
the new roles system.
First, let's first see how the new roles work, then we'll discuss how to migrate them from the old permissions
system to the new roles system.

Permissions and roles


PlayFab features a powerful, fine-grained permissions model with more than 80 individual permissions to
determine exactly what users are allowed to do. Most features in the Game Manager can be completely turned
off, set to read-only mode, or set to read-write mode.
For example, you may want your Customer Service rep to be able to edit a player profile, but not view revenue
data. And you may want a Product Manager to be able to view revenue data, but not upload new multiplayer
game server builds.
Previously, permissions had to be set individually for each user, and for each title. This was cumbersome,
especially for large studios with many users, titles, and permissions sets.
And worst of all, if a permission policy changed, or a new feature was added, you needed to go through and
manually edit the permissions for every user.
Now, however, studios can define a role as a collection of permissions, and then assign those roles directly to
users. You can edit a role at any time, and all users assigned to that role will immediately have their permissions
changed.
For convenience, you can even assign multiple roles to a user. For example - you could define a Customer
Support role, with permission to edit player profiles, and a Data Scientist role, with permission to view all events
and see all dashboards, and assign both to a single user.

Creating custom roles


The first step in using the new system is to define roles.
By default, PlayFab comes with two predefined roles:
1. Title Admin
2. Dashboard
Title Admin gives full permissions to a given game title, while Dashboard only gives permission to view the
dashboards for the title.
There is also a third, special role -- Studio Admin .
Studio Admins are special users who have permission to create titles, define roles, and have automatic Title
Admin rights to every title in the studio.
Here are the steps to create a new role:
1. Login to PlayFab with your developer account.
2. Ensure you are a Studio Admin (you will know that you are if you see the following options next to your
studio name). If you are not the Studio Admin, please contact the Studio Admin to setup the permissions
according to this tutorial.

3. Select Users and Roles from the list of options.


4. Select the Roles tab at the top of the screen. You should now see a list of all the Roles in the system.

5. Select the New Custom Role button to create a new role. Give your new role a name, and check off the
permissions you wish to include. Generally, all permissions follow this pattern:
You can enable or disable the entire feature using the top-most option Permission (1) .
You can show or hide the navigation tab using the Permission tab (2) .
Each Permission has a read-only and read-write option. The read-write option has Edit at the end
(3) and (4) .
6. Select the Save Role button when you're done.

Assigning roles
Once you've created a role, you can assign the role to users in a title.
Roles apply at the title level. If you have five titles, and you wish a given user to have the same role for each title,
you must give the user that role for each title.
This gives you the most flexibility. Under this system, a given user could be a Title Admin for one title, a Product
Manager for another, and a Customer Service rep for a third, all under the same studio.
Here are the steps to assign a role:
1. Login to PlayFab with your developer account. As mentioned previously, make sure you are a Studio Admin.
2. Select Users and Roles from the list of options. You will see a list of users for your studio.
3. Select Settings for the user for whom you wish to assign roles.
4. Select the Roles tab. You will see a list of all titles in your studio, and any roles that user already has for each
title.
5. Select Assign Roles for each title for which you wish to give the user a role. You will see a list of your Roles.
Check any role you wish to give the user on that title.
6. After you have assigned Roles, be sure to select Save User , otherwise your role assignments will be lost.

Migrating to the new roles system


If you have an existing title, and you have already given users custom permissions, we will automatically create
new roles for these users.
After a user has been migrated to their new custom role, you can rename the role.
Because Studio Admin is a new permission level, this will automatically be granted to users who have Title
Admin on all titles in a studio.

Conclusion
Roles are a powerful and flexible new way to determine who can do what in Game Manager.
Going forward, you should use roles to assign permissions. Existing custom permissions will continue to
function, but you cannot change the permissions without migrating over to the new roles system.
Secret key management
5/24/2022 • 2 minutes to read • Edit Online

PlayFab developer secret keys allow your Title to make PlayFab Admin and Server API calls. A secret key, also
called a developer key, is strongly coupled with a PlayFab Title.
Using the Secret Keys page in Game Manager , you can create, delete, disable, and set your keys to expire.
This enables you to rotate the secret keys for your titles (which was difficult to do in the past.) It also allows you
to grant temporary access to your titles.

NOTE
Never include your developer Secret Key in a client build that you send to your customers. Doing so exposes your title to
abuse.

To manage the secret keys for your Title:


1. Sign in to Game Manager .
2. Select your Title.
3. In the upper-right corner, select the gear icon.
4. Select Title settings , then select the Secret Keys tab.

The Secret Keys page provides options to Delete keys, view the Status of each key, and its Name , Value , and
Expiration time, if it has one. This table lets you audit the keys that are available.
You can rename, enable, disable, or set expirations for existing keys via the dashboard. To see the options for a
key, simply select it. Each title starts with a default key.
To rotate your keys:
1. Select New Secret Key .
2. Enter the Name of the key, and an optional expiration date.
3. Update your code to use the new key.
4. Disable the old key. Select the old key and then on the Edit Secret Key page, select the Disable checkbox.
5. Select SAVE SECRET KEY .
IMPORTANT
If your old keys are compromised, rotate the keys to return your Title to a secured state.

This flow is zero-downtime, and you can safely roll back each step until you delete the old key. If there are issues
at the first step, you can delete your new key. No one should be using it.
At step two, both keys are active, so you can roll your code forward or back safely.
At step three, you can re-enable the key while you fix whatever was still depending on it.
When the process is complete, you do not need to delete the old key. If you delete that key, it cannot be
recovered. The delete is permanent and irrevocable.
Setting a key to Expire is useful when you need to give someone temporary access to your Title.
For example, if you have a contractor working on your game, you can give them keys that only have access for
as long as you expect them to need it. If they require access beyond the original expected expiration date, you
can reset the expiration date to extend the lifetime of the secret key.
Two-factor authentication
5/24/2022 • 2 minutes to read • Edit Online

Two-factor authentication allows you to reinforce security on your PlayFab Game Manager account by adding
one more step to the authentication process.
It does so by adding a device-factor to the authentication process, which only allows you to authenticate, if you
possess a certain device specifically registered for this purpose.

Configuring two-factor authentication


Install a Two-Factor Authentication app to your device. You can search on your own application, or select
your platform from the following list:
iPhone, iPad, and iPod Touch
Android phone or tablet
Windows phone or tablet
The steps are basically similar on all the platforms. This example shows an Android-based device, and a Google
Authenticator application.
Once the application is downloaded;
Open it and follow the instructions.
Select the Begin button (1) .
Follow through the tutorial for the app, if there is any (1) .
Then select one of two options to add your PlayFab account:
Either scan a bar code (1) .
Or type in the key manually (2) .
Whichever option you choose, follow to the PlayFab website and navigate to Game Manager . On the
Dashboard tab:
Select the Account panel (1) .
Then select My Profile (2) .
The Account settings will open.
Verify that the Enable two-factor authentication checkbox is checked.
Depending on which option you have chosen, use the code (1) or a bar code (2) to add a new account
using the application on your device.

Once this is done, you will obtain a two-factor code.


Head back to the Profile settings in the PlayFab Game Manager :
Enter the code you received (1) .
Select Save Profile button (2) .
Testing
Log out of your PlayFab account and try to log in again. The first step of the authentication process will look
normal (see example provided below).

The second step will require you to use your two-factor code. The code is available at any time, and you can
access it using the application you installed on your device.
Once the correct two-factor code has been entered, you should be logged in.
This concludes setting up two-factor authentication for PlayFab.
What is PlayFab Authentication?
5/24/2022 • 2 minutes to read • Edit Online

PlayFab helps you leverage Authentication of your players using a breadth of providers. You can use
authentication based on the device and allow your players to link their favorite accounts to enable roaming and
recovery. Use this section to learn more about how PlayFab helps you enable Player Auth.
PlayFab also supports multiple methods for GameManager Login (SAML, AAD and PlayFab User Authentication).
You can explore these in the Azure Active Directory Authentication section.
Player login
5/24/2022 • 2 minutes to read • Edit Online

The first step in adding PlayFab to any game is to log in the player. Logging in the player returns a security token
that is required for all other API calls.
PlayFab provides a breadth of login providers to enable both anonymous and recoverable login mechanisms.

Anonymous login mechanisms


Anonymous login mechanisms are the simplest to use. They require zero input from the player, so that there's
no friction to the first time user experience - and they create a unique account in PlayFab for each player.
This is the most common login mechanism to use initially (especially for mobile games). Being anonymous,
these methods can uniquely identify a device, but contain no recoverable information about this player. If the
player loses or breaks their device, the account is lost, and may be very difficult to recover.

Recoverable login mechanisms


Recoverable login mechanisms require some identity information from the player. The player must either
authenticate with an external provider (e.g. Facebook, iOS, Google, Kongregate, PlayStation, Steam, Xbox Live,
etc.), or manage the login directly with PlayFab, by using either a user name or email address and password.

Best practices
You should begin by reading the login best practices guide. Make sure that your game enables your players to
join in and start playing quickly and easily, while providing them with a safe and secure method of getting
access to their game data on multiple devices.
Login basics and best practices
5/24/2022 • 4 minutes to read • Edit Online

Platform-specific authentication tutorials


While all of the platform-specific authentication tutorials demonstrate logging in with LoginWithCustomID, the
uses for this login in a published game are limited to pairing a PlayFab account to a pre-existing database, or
another back-end system.
Otherwise, it is very rare for a published title to use a custom ID for a primary login, since in most cases you
want to capture additional information on the player's platform.
Why we demonstrate this first
Bluntly - because it's the easiest. A custom ID can be anything, and it makes it easier to call your first API. Once
you get serious about developing and releasing your title, it is very likely you will switch to another login
mechanism.
Best practice
Unless you know exactly why you want LoginWithCustomId in your released title, you should migrate to another
login mechanism before you launch.

Anonymous login mechanisms


Anonymous login mechanisms are the simplest to use. They require zero input from the player, so there's no
friction to the first time user experience - and the result is a unique account in PlayFab for each player. This is the
most common login mechanism.
These logins include:
LoginWithIOSDeviceID
LoginWithAndroidDeviceID
LoginWithCustomID
Since they are anonymous, these methods can uniquely identify a device, but contain no recoverable
information about the player. If the player loses or breaks their device, the account is lost, and may be very
difficult to recover. In most cases the account is simply orphaned and not retrievable.
So why use it? Because it's the lowest possible barrier to entry for the player, requiring no interaction. It gets the
player trying your game with minimal effort, while creating an account they can get back to for continuity (as
long as they have that device).
Best practice
Your game should use an anonymous login for creating a new account and linking new devices to an existing
account. We recommend this because some players may abandon a game that asks for an e-mail or identifiable
information.
However, once the anonymous login is complete, you should provide the option to add recoverable login
credentials, and provide some explanation regarding the benefits.
In particular, you should make sure that paying customers are guided to the recoverable login systems, to
prevent loss of their accounts. A free account lost forever is a disappointment...
A paid account lost forever affects revenue.
iOS devices
For iOS devices, the player ID changes if they uninstall your game, and then re-install it. One way to make sure
you have a consistent ID on iOS is to save the device ID for the player to the iTunes KeyChain, so that you can
read it from there on game start, and use it to sign in.
You must determine how to generate unique custom IDs for any other device or platform. Custom IDs are an
effective alternative for other platforms or devices, but you must generate your custom IDs with care. If they are
too simple, you risk hackers stealing the accounts of others.
android devices
For latest best practices, see Google's guidelines on user data ids.

NOTE
Binding a recoverable login is only required once per device. Once bound, the game can continue to use the anonymous
login with no drawbacks. See the next section.

An anonymous login is convenient for the player, but it is not required. Your game can rely exclusively on a
recoverable login mechanism. However, your players will be happier if they don't have to type a password every
time they log in.

Recoverable login mechanisms


A recoverable login mechanism requires some identity information from the player. As described above, it can
be paired with an anonymous login for the best player experience.
Pure PlayFab options
The simplest options are:
LoginWithPlayFab
LoginWithEmailAddress
If used, the e-mail or username-plus-password are authenticated directly by PlayFab. The account is recoverable
by the e-mail or username, even if the user forgets their password. The login is generally secure (you can
implement your own password strength check into your game to improve this).
Third party API options
These require separate API calls to another service, but do not require additional SDK installations:
LoginWithKongregate
LoginWithSteam
LoginWithTwitch
LoginWithGameCenter (iOS only, and provided you require secure authentication.)
Secure authentication happens between your user, and the 3rd party service API call.
Third party SDK options
These require a separate SDK installed into your game. Secure authentication happens within the 3rd party SDK.
LoginWithFacebook
LoginWithGoogleAccount
In all 3rd party options, those services process the login credentials, and you pass a secure token to the
appropriate PlayFab login method. PlayFab remains unaware of the login credentials for those services.
More best practices
Use an appropriate anonymous login for a basic login, and encourage your player to link to a recoverable login.
You should pick any one or more of the recoverable mechanisms with which you are comfortable and familiar.

TIP
Account recovery only requires one recoverable login, so don't pressure your player to use all of them.

Insecure login mechanisms


One benefit of recoverable login mechanisms is they are more secure than logging in with a custom ID, as they
require verified authentication with a third party rather than relying on a user's custom ID remaining a shared
secret.
However, it is worth noting that LoginWithGameCenter specifically can be similarly insecure if you do not
require secure authentication with Apple. If you plan to use Game Center as a recoverable login mechanism for
a game with any multiplayer interaction, it is strongly recommended you implement and require secure
authentication as described in the LoginWithGameCenter documentation.

Conclusion
Anonymous login is great, and it provides the user with a fully automated login process. The downside is
account recovery, which is sometimes impossible without a recoverable login.
The following flow chart describes anonymous login followed by adding a recoverable login mechanism.
Best practice
Use the appropriate anonymous login for your device, paired with one or more options for account recovery.
Account linking quickstart
5/24/2022 • 9 minutes to read • Edit Online

This Account linking quickstart demonstrates how to bind an account to multiple devices and login mechanisms.
A single PlayFab account can be accessed by many devices and login credentials. As we discuss in our tutorial
Login basics and Best Practices, there are two forms of user authentication:
1. Anonymous
2. Recoverable

Adding a recoverable login to an existing anonymous account


It is very common for your first login to be an anonymous one. This gets your player into the game, friction-free.
But once a player becomes invested in your game, you should prompt them to add a recoverable login method,
which makes their account recoverable in the case of device failure or other issues.
This section covers adding a recoverable login mechanism to an anonymous account.

NOTE
An anonymous login is still relevant, and can continue to be the primary frictionless login for the player. Many players will
only use these options again if they are attempting to recover their account, are using platform-specific features, or link a
second Anonymous device.
The focus of this tutorial is at the bottom of the preceding image, with the cells: AddUsernamePassword ,
LinkWithFacebook , or LinkWithGoogle . These indicate a few of the larger set of options available for
recoverable login mechanisms.
AddUsernamePassword is used to enable either/both of: LoginWithPlayFab and LoginWithEmailAddress.
These options store username/email/password credentials with PlayFab directly. In order for a player to
recover their account, your game, website, or customer service can trigger:
SendAccountRecoveryEmail for that email address. If a player enters a bogus email address, you can
still use the PlayFab Game Manager to update the email address for the player, though it's important
to make sure your customer service representatives are trained to watch out for common social
engineering tricks, so that they're only updating the email address of the actual owner of the account.
The third-party recoverable login mechanisms each involve prompting the user to log in via an appropriate SDK
or third-party API call. Linking that account to PlayFab generally follows the same pattern:
1. First, prompt the user to log into that service (more details in Login basics and Best Practices).
2. Once you have logged in, those services will provide some kind of token, which can be passed to PlayFab.
3. This allows PlayFab to safely link to that account without being aware of the user's credentials in that service.
NOTE
Some services require that PlayFab have some additional information, such as an Application ID, in order to make the
authentication call to that service for your game. Please be sure to check the Add-on Marketplace page for the service
in question as part of setting up your title.

Best practice
Use an anonymous login to create new players with zero friction. After a tutorial phase, gently encourage
players to link your preferred choice of recoverable credentials to their account.
If you're using a third-party authentication system, retrieve the appropriate token from that service (via API calls
or SDK functions), then call the appropriate PlayFab API to link the player's account from that service to their
PlayFab account: LinkFacebookAccount, LinkGameCenterAccount, LinkGoogleAccount, LinkKongregate,
LinkSteamAccount, LinkTwitch, LinkWindowsHello.
Best practice
For user privacy, do not save or store any user credentials (this is also one of many steps required for
COPPA compliance - and if that's a requirement for your title, please be sure to talk to your legal counsel
to confirm your compliance).
If you are using the PlayFab credentials, or calling a third-party API directly, you should clear their login
information from memory as soon as possible. Generally, the third-party SDKs take care of this for you.
Do not keep any identifiable or secure information in memory longer than you need it, and don't save it
to a file or remote location. The PlayFab APIs are designed to utilize only the minimum required
information.

Add new devices to an existing recoverable account


PlayFab allows multiple logins and devices to access the same account. When set up properly, a player may play
the game on any device, set that device down, pick up a new device (even a different type, brand, platform, or
OS), and resume playing the same game, with all of their data intact.
Requirement
The player must possess two devices:
Device1 - Set up with an account and recoverable credentials already properly set up. It is also ideal if the
second device is not bound to an account. This process will orphan any account which only has the second
device's ID as a login mechanism, making it irrecoverable. However, PlayFab has options to safely detect and
warn against this case.
All activity in this scenario takes place on Device2 - To begin, the user login flow for the second device must
be reversed. You must provide the user an option to log in via a recoverable mechanism, and not
automatically log in with the device ID.
Failure to do this step will result in an awkward player experience, where they will be warned against losing an
account they never intended to make.
So the flow for the various conditions is as follows - and note that in all cases, there's only one player account,
which does have a recoverable account linked.
Device1 State : Device ID is bound to the player account. Device2 State : Device ID is not bound to the
player account.
After signing into the player account on Device2 (using the recoverable account credentials), make a call to
GetPlayerCombinedInfo.
For each device type returned in that information, the most-recently signed in device ID is returned in
the result.InfoResultPayload.AccountInfo.
Since Device2 has not yet been linked to this player account, the relevant device ID
(AccountInfo.IosDeviceInfo , AccountInfo.AndroidDeviceInfo , etc.) will not match the Device2 ID .
Device1 State : Device ID is bound to the player account. Device2 State : Logged in with recoverable
credentials, but Device ID is not bound to the player account.
Now that we've verified that Device2 is not bound to this account, we can try to bind it.
Call the appropriate LinkAndroidDeviceID , LinkIOSDeviceID , or other device-specific API call.
If successful, you're done, resume normal gameplay.
But as with any API call, be prepared to capture errors. Specifically, look for an error return that the device is
already linked to an account.
Under this condition, prompt the player with a Do you want to bind this device to this account
message.
Be sure to provide information that the other account may be lost if they continue.
If the player accepts this warning, re-send the link-request with the property ForceLink set to True .
This will unlink the Device2 ID from the old account, potentially orphaning that account if no other login
mechanisms are linked to it, and bind it to the new account.
Best practice
Use CloudScript, or a PlayStream event to record information on abandoned accounts somewhere where your
customer service reps might be able to recover it, if the player made a mistake.

NOTE
Even something as simple as writing the PlayFabId to a Cloud-based log file may save an account for a dedicated player.

Device1 State : Device ID is bound to the player account. Device2 State : Device ID is bound to the player
account.
At this point, both devices now play on the same account, and both devices can use frictionless login safely.

Bind a frictionless device ID to an existing recoverable account


This scenario is very similar to the situation above, except the account was created using Recoverable
Credentials.
You can convert an existing game login screen into a frictionless login by binding an anonymous login after the
fact. The steps here are nearly identical to the condition above, only with a single device (which is simply
Device2 in the flow above).
Device State : Device ID is not bound to the player account.
After performing a recoverable login with the device, call GetPlayerCombinedInfo. Again, determine whether the
device ID matches the bound device ID, via the info returned in result.InfoResultPayload.AccountInfo.
Since the device has never signed into the account, the relevant device ID (AccountInfo.IosDeviceInfo ,
AccountInfo.AndroidDeviceInfo , etc.) will not match the device ID.
Device State : Logged in with Recoverable Credentials, but the device ID is not bound to the player account.
Since the device is not bound to this account, we can try to bind it. Call the appropriate LinkAndroidDeviceID ,
LinkIOSDeviceID , or other device-specific API call.
If successful, you're done, resume normal gameplay.
But again - be prepared to capture errors. Specifically, look for an error return that the device is already linked to
an account. Under this condition, prompt the player with a Do you want to bind this device to this account
message.
Be sure to provide information that the other account may be lost if they continue. If the player accepts this
warning, re-send the link-request with the property ForceLink set to True .
This will unlink the device ID from the old account, potentially orphaning that account if no other login
mechanisms are linked to it, and bind it to the new account.
Best Practice :
Use CloudScript, or a PlayStream event to record information on abandoned accounts somewhere where your
customer service reps might be able to recover it if the player made a mistake. Even something as simple as
writing the PlayFabId to a cloud-based log file may save an account for a dedicated player.
Device State : Device ID is bound to the player account.
At this point, a frictionless login can be used with the device, instead of the recoverable credentials.

Other best practices


The steps above involve prompting the user before logging in. Frictionless login involves logging in without
asking the player first. You can find an ideal middle ground with the following suggestions:
Frictionless login APIs: Your frictionless logins all have a request parameter called CreateAccount .
Examples:
AndroidRequest .CreateAccount
IosRequest .CreateAccount . Select true or false for this property with the following guidelines:
On star tup :
In your login scene, your game can immediately attempt a Frictionless login with CreateAccount=false .
If this succeeds, this player has already logged into the game with this device, and they can safely skip
directly into the game scene. Capture the error callback for this call, and have it display the first-time login
options.
First Time Login Scene : For any device with a frictionless login capability, this scene should include a
Play Now button, along with buttons that let the player log into an existing account via Facebook, Twitch,
Google, or other recoverable login options. The Play Now button should activate the frictionless login
with CreateAccount=true .
Log Out : Provide a Log Out button that returns to your first-time login scene, but does not
automatically activate the frictionless login. This allows a user the option of abandoning their device-
bound account by logging in with a Recoverable option, and then binding the device to that account.
With these suggestions, you can avoid most awkward scenarios, where users are asked to abandon an account
when binding multiple devices to the same account.
Platform-Specific Authentication
5/24/2022 • 2 minutes to read • Edit Online

PlayFab supports a wide variety of authentication providers. This allows your title to support different
authentication methods and give your players options.
What this means is that your players can choose how they prefer to verify their identity and sign in using a
method that's most natural to them.
Select authentication providers based on what is most meaningful for the players on your target platforms and
distribution methods. For example, if your title is released on Xbox, it will make sense to offer Xbox Live sign-in
as a way to authenticate their identity.
Apple
Set up Apple sign-in for PlayFab
Facebook
Setting up PlayFab authentication using Facebook and HTML5
Setting up PlayFab authentication using Facebook and Unity
Google
Setting up PlayFab authentication using Google and HTML5
Setting up PlayFab authentication using Google Play Games Sign-In in Unity
Kongregate
Setting up PlayFab authentication using Kongregate and HTML5
Setting up PlayFab authentication using Kongregate and Unity
Phaser
Setting up PlayFab authentication in Phaser.io
PlayStation
Setting up PlayFab authentication using PlayStation (secure link)
If you're unable to access the above secure link, see Request access.
Steam
Setting up PlayFab authentication using Steam and Unity
Twitch
Setting up PlayFab authentication using Twitch and HTML5
Windows and Xbox
Authenticate Xbox Live users using PlayFab's Xbox Live Helper Library (recommended)
Setting up PlayFab authentication using Universal Windows Platform
Integrating the Universal Windows Platform with PlayFab
Platform-Specific Authentication Tutorials
5/24/2022 • 2 minutes to read • Edit Online

These tutorials provide basic information and best practices for setting up PlayFab authentication.
Login basics and Best Practices
Running an HTTP server for testing
These tutorials show you how to set up PlayFab authentication on specific platforms.
Setting up PlayFab authentication using Facebook and HTML5
Setting up PlayFab authentication using Facebook and Unity
Setting up PlayFab authentication using Google and HTML5
Setting up PlayFab authentication using Google Play Games Sign-In in Unity
Setting up PlayFab authentication using Kongregate and HTML5
Setting up PlayFab authentication using Kongregate and Unity
Setting up PlayFab authentication in Phaser.io
Setting up PlayFab authentication using Steam and Unity
Setting up PlayFab authentication using Twitch and HTML5
Setting up PlayFab authentication using Universal Windows Platform
Integrating the Universal Windows Platform with PlayFab
Running an HTTP server for testing
5/24/2022 • 3 minutes to read • Edit Online

In some scenarios, you may need to run a local HTTP server for test purposes. For example, if you are following
our tutorials for setting up PlayFab authentication using Facebook and HTML5, Google and HTML5, or Twitch
and HTML5, and you do not have a remote server with a domain, you may find this tutorial useful.

Prerequisites
Installed Node.JS

Installing HTTP server using NPM


Run the command line/terminal on your system (it doesn't matter which directory you are currently in).
Execute npm install -g http-server . Once NPM finishes, you have the tiny HTTP-server installed. That's it.

Serving files
Create a new folder on your system from where you want to serve your static files. There are no specific
restrictions for path on Windows.
On Mac OS, you may want to check for access on the folder. Inside of the newly created folder, create a file called
index.html .
Fill the file with the content provided below.

<!doctype html>

<html lang="en">
<head>
<meta charset="utf-8">
<title>My Page</title>
</head>

<body>
<p>Hello world!</p>
</body>
</html>

Run the command line/terminal and cd to the folder with your index.html file, then:
1. Execute http-ser ver .
2. HTTP-ser ver will start serving files from your current directory.
3. It will also print out all the IP endpoints that the server is listening for.
4. Use one of them to reach your web-server through the browser.
5. Observe your page being loaded.
You can optionally specify a port to run the server on.
Example : Execute http-server -p 80 to run your server on por t 80 . If a port is occupied, you will have to
find what application is using this port and shut it down before you attempt to run the HTTP server again.
Serving files with a custom domain name
When testing different SDKs, for example, Google or Facebook, you will notice that some services can only be
configured with a certain valid domain name.
For instance, they do not accept a plain IP address + port. Certain services use such a configuration to ensure
that your browser fetches your code from a specific, secure domain.
They also often use this configuration to ensure that a user can only log into your application from your domain,
and that nobody else can fake it and steal user data.

NOTE
While this is an important and useful security restriction, it may produce complications when trying to locally test your
code.

If you run your server on Port 80, and your use-case is simple enough, you can utilize the HOSTS file on your
operating system to access your HTTP server through a valid domain name.
The HOSTS file is a special file available on both Windows and Mac OS. It allows you to override certain domain
names with custom endpoints. Schematically, the HOSTS file looks like this:

IP_ADDRESS_1 DOMAIN_NAME_1
IP_ADDRESS_2 DOMAIN_NAME_2
IP_ADDRESS_3 DOMAIN_NAME_3

# This is comment
# IP_ADDRESS_4 DOMAIN_NAME_4 <- this entry is commented out and is inactive
...

Each line represents exactly one entry. When you try to reach DOMAIN_NAME_1 , your browser will direct your
request to IP_ADDRESS_1 .
The same applies for each entry in the HOSTS file. In the preceding example, entry number 4 starts with # .
This is a syntax for comment.
By commenting out certain entries you may disable them, without necessarily removing them from the HOSTS
file.
playfab.example is a valid domain name, but it is unlikely that your browser will reach any website with it. By
adding the following entry to your HOSTS file, you will be able to reach your local HTTP server with that domain
name.

127.0.0.1 playfab.example

On Windows OS, the HOSTS file is normally located at:


C:\Windows\System32\drivers\etc\hosts .
On Mac OS, the HOSTS file is normally located at:
/private/etc/hosts .

WARNING
When entering your domain name in your browser address bar, always make sure to include the schema:
http://playfab.example.
Setting up PlayFab authentication using Facebook
and HTML5
5/24/2022 • 3 minutes to read • Edit Online

This tutorial is designed to guide you through PlayFab authentication using Facebook and HTML5/JavaScript.

Requirements
A Facebook account for testing.
A registered PlayFab title.
A familiarity with Login basics and Best Practices.
A minimal server, with a valid domain name to serve static HTML file.

NOTE
If you are unsure if you have the proper requirements for this activity, please consult the Running an HTTP server for
testing tutorial.

Server and domain


As part of the requirements to set up your PlayFab authentication, you must have a server with a valid domain
to follow. If you do not have a registered domain and remote web server yet, please follow our Running an HTTP
server for testing tutorial to run a local web server with a valid domain name.
Throughout this guide, we will assume your domain is 'http://playfab.example'.

Registering a Facebook application


Start by navigating to the Facebook Developer Portal.
1. Hover your mouse over the My Apps button.
2. Select Add a New App from the drop-down menu, as shown in the example provided below.
A new Application pop-up will open.
1. Enter a name for your Application in the field under Display Name .
2. Enter a contact email address in the field under Contact Email .
3. Select the Create App ID button to save.

NOTE
Make sure to come up with your own unique application name and email, as shown in the example provided below.

1. Navigate to the Settings tab.


2. Select the Basic sub-tab.
3. Locate your Application ID .

NOTE
Copy your Application ID to a safe place, we will use it later to set up the Facebook SDK .
1. Go to the menu on the left of your screen and select the +Add Product item.
2. Locate Get Star ted in the Facebook Login area and select it.

The page should open to display the example shown below.


1. Make sure that Facebook Login/Settings is opened on the menu to the left, and you are in Client OAuth
Settings .
2. Verify that both the Client OAuth and Web OAuth are on (marked Yes ).
In the Client OAuth Settings screen:
1. Set the Valid OAuth redirect URIs to your own auth page URI .

NOTE
This will be playfab.example in your case.

2. Select Save Changes to commit.


On the Application Manager page:
Open Settings/Basic (1) in your menu.
Select the Add Platform (2) button.
A pop-up will appear on your screen:
1. Select the Website icon .

The Website configuration panel should now appear.


1. In the SiteURL field, enter your auth page URL (this will be playfab.example in your case).
2. Select Save Changes to commit.
Testing
Use the following HTML file to test your PlayFab authentication using Facebook.

NOTE
Make sure to replace YOUR-APPLICATION-ID and YOUR-PL AYFAB-TITLE with your own.

<!DOCTYPE html>
<html>
<head>
<script>
// This function will be called when Facebook SDK is loaded
window.fbAsyncInit = function() {

// Make sure to use your own App ID for the configuration


FB.init({
appId : 'YOUR-APPLICATION-ID',
xfbml : true,
version : 'v2.9'
});

// Record PageView event for analytics


FB.AppEvents.logPageView();
};

// Facebook SDK loader. Creates a script entry to load the SDK


(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/sdk.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
</script>
<script src="https://download.playfab.com/PlayFabClientApi.js"></script>
</head>
<body>
<p>Facebook Auth Example</p>
<button onclick="loginWithFacebook()">Log In with Facebook</button>
<script>
// This method is invoked when you press the button
function loginWithFacebook() {
logLine("Logging in via Facebook...");

// Standard practice: make call to FB.login.


// This will show Facebook popup window. To prevent browsers from locking it,
// always make sure to call it from Button click event
FB.login(function(response){
if(!response.authResponse){
logLine("Problem authenticating via Facebook!");
} else {
loginWithPlayfab(response.authResponse.accessToken);
}
});
}

function loginWithPlayfab(accessToken){

logLine("Logging in via PlayFab...");

// When given accessToken, make call to LoginWithFacebook API Call


// Make sure to use your own PlayFab Title ID
PlayFabClientSDK.LoginWithFacebook({
AccessToken: accessToken,
TitleId: "YOUR-PLAYFAB-TITLE",
CreateAccount: true
}, onPlayFabResponse);
}

// Handles response from playfab.


function onPlayFabResponse(response, error) {
if (response)
logLine("Response: " + JSON.stringify(response));
if (error)
logLine("Error: " + JSON.stringify(error));
}

function logLine(message) {
var textnode = document.createTextNode(message);
document.body.appendChild(textnode);
var br = document.createElement("br");
document.body.appendChild(br);
}
</script>
</body>
</html>

Request the following file from your server using the domain you set up during Facebook Application
configuration ( playfab.example in our case).
1. Once the Facebook Auth Example page opens, select Log In with Facebook button.
2. Follow any Facebook instructions in the pop-up window.
Watch the output.
You will obtain a PlayFab session ticket. At this point you have successfully configured PlayFab and Facebook
authentication using HTML5 and JavaScript.
Setting up PlayFab authentication using Facebook
and Unity
5/24/2022 • 6 minutes to read • Edit Online

This tutorial guides you through an example of PlayFab authentication using Facebook and Unity.

Requirements
Unity 5+ and a created project.
Facebook account for testing.
Facebook SDK imported into the project.
Registered PlayFab title.
PlayFab SDK imported into the project with a configured title reference.
Familiarity with Login basics and Best Practices.

Implementation
Registering a Facebook application
Start by navigating to the Facebook Developer Portal:
1. Move your mouse over the My Apps button.
2. Select Add a New App , as shown on the picture below.

A new Application pop-up will open.


1. Enter a name for your Application .
2. Enter a Contact Email .

NOTE
Make sure to come up with your own unique Application Name and Email, as shown on the picture below.
1. Navigate to the Settings tab.
2. Then move to the Basic sub-tab.
3. Locate your Application ID .
Copy it somewhere to a safe place that is easily accessed. We will use it later to set up the Facebook
SDK.

Navigate to the Facebook Access Token Tool.


1. Locate your App in the list.
2. Verify that it has an assigned User Token .

NOTE
If you do not have an assigned user token, request one using the button to the right of your screen. Refer to this page
whenever you need a fresh user token. If authorization fails during testing on a PC, token expiration may be the most
likely reason. Refresh the page to get a new user token and test again.
1. On your Application Manager page, navigate to + Add Products .
2. Locate the Facebook Login entry and select Get Star ted .

A page with Login product settings should open.


1. Make sure that you have the Login product Settings page opened.
2. Verify that both Client OAuth and Web OAuth are on.

Setting up Facebook SDK


Open your Unity Project :
1. Select Facebook in the file menu.
2. Then select Edit Settings .

The Inspector window will display the current Facebook SDK configuration.
Enter your Application ID in the corresponding field, as shown in the following picture.

Simple authentication script


Create a new Game Object , and rename it to PlayfabFacebookAuthExample , as shown in the following
picture.

1. Create a script called PlayfabFacebookAuthExample.cs .


2. Add it to the Game Object as shown on the picture below.

Inside PlayfabFacebookAuthExample.cs place the following code.

// Import statements introduce all the necessary classes for this example.
using Facebook.Unity;
using PlayFab;
using PlayFab.ClientModels;
using UnityEngine;
using LoginResult = PlayFab.ClientModels.LoginResult;

public class PlayfabFacebookAuthExample : MonoBehaviour


{
// holds the latest message to be displayed on the screen
private string _message;

public void Start()


{
SetMessage("Initializing Facebook..."); // logs the given message and displays it on the screen
using OnGUI method

// This call is required before any other calls to the Facebook API. We pass in the callback to be
invoked once initialization is finished
FB.Init(OnFacebookInitialized);

}
private void OnFacebookInitialized()
{
SetMessage("Logging into Facebook...");

// Once Facebook SDK is initialized, if we are logged in, we log out to demonstrate the entire
authentication cycle.
if (FB.IsLoggedIn)
FB.LogOut();

// We invoke basic login procedure and pass in the callback to process the result
FB.LogInWithReadPermissions(null, OnFacebookLoggedIn);
}

private void OnFacebookLoggedIn(ILoginResult result)


{
// If result has no errors, it means we have authenticated in Facebook successfully
if (result == null || string.IsNullOrEmpty(result.Error))
{
SetMessage("Facebook Auth Complete! Access Token: " + AccessToken.CurrentAccessToken.TokenString
+ "\nLogging into PlayFab...");

/*
* We proceed with making a call to PlayFab API. We pass in current Facebook AccessToken and let
it create
* and account using CreateAccount flag set to true. We also pass the callback for Success and
Failure results
*/
PlayFabClientAPI.LoginWithFacebook(new LoginWithFacebookRequest { CreateAccount = true,
AccessToken = AccessToken.CurrentAccessToken.TokenString},
OnPlayfabFacebookAuthComplete, OnPlayfabFacebookAuthFailed);
}
else
{
// If Facebook authentication failed, we stop the cycle with the message
SetMessage("Facebook Auth Failed: " + result.Error + "\n" + result.RawResult, true);
}
}

// When processing both results, we just set the message, explaining what's going on.
private void OnPlayfabFacebookAuthComplete(LoginResult result)
{
SetMessage("PlayFab Facebook Auth Complete. Session ticket: " + result.SessionTicket);
}

private void OnPlayfabFacebookAuthFailed(PlayFabError error)


{
SetMessage("PlayFab Facebook Auth Failed: " + error.GenerateErrorReport(), true);
}

public void SetMessage(string message, bool error = false)


{
_message = message;
if (error)
Debug.LogError(_message);
else
Debug.Log(_message);
}

public void OnGUI()


{
var style = new GUIStyle { fontSize = 40, normal = new GUIStyleState { textColor = Color.white },
alignment = TextAnchor.MiddleCenter, wordWrap = true };
var area = new Rect(0,0,Screen.width,Screen.height);
GUI.Label(area, _message,style);
}
}
Testing
Running the application in the editor
1. Select the Play button. Once Facebook is initialized (and an authentication call is made), a Facebook
authentication dialog will appear in your game view.
2. Enter the User Token .
3. Select the Send Success button, as shown in the following picture.

Check the console output. It should render our debug statements, as shown on the picture below.
If you see no errors, this means that authentication was successful.

Running the application on Android


Before launching the application on Android, you are required to perform additional configuration steps:
First, you need to ensure you have the Android platform selected, and the unique Package ID set (as
indicated in the example below.

NOTE
Please make sure to create your own unique Package ID .

TIP
Optional step : Install Open SSL and add it to the PATH environment variable. If it is missing, Unity will produce a
harmless error during the build. This error does not stop the build, or effect the execution.

Next, in your Facebook Application console:


1. Navigate to Basic settings.
2. Select + Add Platform , as indicated in the example provided below.
Then select Android from the list of available platforms.

A panel with platform-specific settings will appear.


Fill in your Package ID .
Select Save (the Save button is hidden in the bottom right corner of the page).
Build and run the application normally on your Android Device.
The application should welcome you with a Facebook sign-in page.
Once you sign in, watch the message on the screen as it changes.
Finally, you should be presented with a message indicating successful authentication in PlayFab. The entire
procedure is illustrated in the example provided below.

Running the application on iOS


Before launching the Application on iOS, you have to perform additional configuration steps.
First, ensure that you have the iOS platform selected.
Then, set a unique Bundle ID as indicated in the example provided below.
Please make sure to create your own unique Package ID .
Next, in your Facebook Application Console :
1. Navigate to Basic settings.
2. Select + Add Platform , as indicated in the example provided below.

Select iOS from the list of available platforms.


A panel with platform-specific settings will appear.
Fill in your Package ID .
Select the Save button (the Save button is hidden in the bottom right corner of the page).

Next, build the application as usual.


Once this is done, open the Project using XCode .
Select the Project to open Project Settings .
Verify that the Bundle ID matches your unique Package ID .
Make sure to select the correct device.

And select the correct Identity Team .

Finally, run the application as normal.


Once started, the application will allow you to log in to Facebook using the web browser.
Once done, PlayFab authentication will be invoked, and a message will indicate the result.
Checking through PlayFab Game Manager
Open your PlayFab title in Game Manager.
Navigate to the dashboard.
Refer to the PlayStream Debugger panel to check for the latest events. You should see the Facebook
authentication event as displayed in the following example.

At this point you have successfully integrated Facebook Authentication for PlayFab.
Setting up PlayFab authentication using Google and
HTML5
5/24/2022 • 3 minutes to read • Edit Online

This tutorial guides you through the process of PlayFab authentication using Google and HTML5/JavaScript.

Requirements
You will need:
A Google account for testing.
A Registered PlayFab title.
Familiarity with Login basics and Best Practices.
At the minimum, a server with a valid domain name to act as a static HTML file. Consult the Running an HTTP
server for testing tutorial for information on how to set one up.

Server and domain


This guide requires a server with a valid domain to follow. If you do not have a registered domain and remote
web server yet, please follow our Running an HTTP server for testing tutorial for information on how to set one
to run a local web server with a valid domain name.
Throughout this guide, we will assume your domain is http://playfab.example.

Registering a Google API project


Start by navigating to the Google API Console:
1. Navigate to Credentials and select it.
2. In the Credentials panel to the right, select the Create button.
1. Fill in the field under Project Name .
2. Select the Create button.

NOTE
It is normal for API Manager to take 10-20 seconds to generate the project.
Once the Project is created:
1. Navigate to the OAuth consent screen .
2. Make sure the correct email is selected.
3. Add a Name for your Application .
4. Select the Save button.

1. Next, navigate to Credentials .


2. Select Create credentials .
3. Then select OAuth client ID .
1. Select Web Application as your Application type .
2. Give your application a Name .
3. Add your domain to Authorized JavaScript origins - PlayFab in our case.
4. Finally, select the Create button to commit your changes.
On the OAuth client screen shown below, the Google API Manager reveals two important pieces of
information:
1. The client ID
2. The client secret .

NOTE
Be sure to copy and save these values in a safe place that is easily accessible, as they will be used in the authorization
process shown later in this tutorial.

Go to the PlayFab Game Manager page for your title.


1. Navigate to Add-ons in the menu.
2. Locate and open the Google Add-on icon/link.
1. Fill in the Client ID .
2. Fill in the Client secret .
3. Then select the Install Google button.

NOTE
As of July 2017, Google API Manager has a bad habit of not hooking the Allowed JS origin domain properly. If you
receive the following error:
"idpiframe_initialization_failed", details: "Not a valid origin for the client: somedomain.com..."
Please remove the credentials and recreate them. There is no need to delete the entire project - just the credentials.

Testing using an access token


In this example, we show how to test using the classic access token approach. Use the HTML file provided below
for your testing.

NOTE
Please make sure to replace YOUR_CLIENT_ID and YOUR_PLAYFAB_TITLE with your own values.
<!DOCTYPE html>
<html>
<head>
<!-- Special meta tag allows you to pass Google Client ID. Replace the content attribute value with your
own Client Id -->
<meta name="google-signin-client_id" content="YOUR_CLIENT_ID"><!-- // TODO: PUT YOUR GOOGLE CLIENT_ID
HERE! -->
<!-- Load Google platform SDK-->
<script src="https://apis.google.com/js/platform.js" async defer></script>
<!-- Load PlayFab Client JavaScript SDK -->
<script src="https://download.playfab.com/PlayFabClientApi.js"></script>
</head>
<body>
<p>Google Access Token Auth Example</p>
<!-- Neat Google button gets styled automatically when Google platform SDK is loaded -->
<div class="g-signin2" data-onsuccess="onSignIn"></div>
<script>
// Invoked when user has signed in with Google
function onSignIn() {
// Retrieve access token
var accessToken =
gapi.auth2.getAuthInstance().currentUser.get().getAuthResponse(true).access_token;

// Execute LoginWithGoogleAccount API call using the access token. Please replace TitleID with
your own.
logLine("Attempting PlayFab Sign-in");
PlayFabClientSDK.LoginWithGoogleAccount({
AccessToken: accessToken,
CreateAccount : true,
TitleId: "YOUR_PLAYFAB_TITLE", // TODO: PUT YOUR TITLE ID HERE!
}, onPlayFabResponse);
}

// Handles response from playfab.


function onPlayFabResponse(response, error) {
if (response)
logLine("Response: " + JSON.stringify(response));
if (error)
logLine("Error: " + JSON.stringify(error));
}

function logLine(message) {
var textnode = document.createTextNode(message);
document.body.appendChild(textnode);
var br = document.createElement("br");
document.body.appendChild(br);
}
</script>
</body>
</html>

Remember to open this page using your web server, and make sure to access this page using the URL you
specified, while configuring Google Project, (PlayFab in our case).
1. Once the page opens, select G Signed In , and follow the general Google authentication flow.
2. When this is finished, the script will try to authenticate on the PlayFab side and output the result.
NOTE
If you already have a Google authentication session running, you will not have to select G Signed In . Everything will
happen automatically.
Setting up PlayFab authentication using Google
Play games sign-in in Unity
5/24/2022 • 6 minutes to read • Edit Online

Tutorial video
NOTE
The audio portion of the following video is currently unavailable. A new recording is pending, and will be available in the
immediate future.

HowTo: Use Google SignIn (GPG) + PlayFab (Unity)


This tutorial illustrates the steps to successfully add Google Play Games sign-in to your PlayFab games, built
with the Unity SDK. Actually, this should be a fairly simple procedure, once you know all the steps.
However, finding all the required information can be tricky. So we will try to centralize all the steps you need to
get this feature working.
You can also download the sample for this tutorial here.

Prerequisites
A project built using the Unity game engine.
A Google developer account.
A PlayFab developer account that has access to a game title in PlayFab.
The PlayFab Unity Editor Extensions & Unity SDK.
The Google Play Games SDK.
Familiarity with Login basics and Best Practices.

Getting started
First, we will start by setting up some basic things in Google Play. There are a few good guides on how to do
this, so we are not going to reinvent the wheel.
1. Create an Application - If you have not done so already, you will need to create an application in the Google
Play Developer Console.
2. Build your game APK, and upload it as an Alpha Build.
Select Manage Releases .
Select Manage Alpha .
Select Upload APK .
3. Setting Up Google Play Games Services - Watch the YouTube video, as the link here is dated, and does not
reflect the latest UI of Google Play Games services.
4. Download the Google Play Games SDK (if you have not done so already) and install it.
5. Install the PlayFab Unity SDK (if you do not know how to do this, follow the Unity3D quickstart guide).

Configuring Google Play Games


You can configure Google Play Games from the toolset that is installed with the Google Play Games SDK. You
can get to these tools by:
Going to the Window tab.
Selecting Google Play Games .
Going to Setup .
Then accessing Android Setup .

Copy your Application ID from the Linked apps section of Game Ser vices in the Google Play Developer
Console, as shown in the example provided below.

Then, populate your app_id and package_name in the resource definition, as shown below.

<?xml version="1.0" encoding="utf-8"?>


<resources>
<string name="app_id">[your app_id]</string>
<string name="package_name">[package name]</string>
</resources>

NOTE
The Client ID that is generated for you when you link the App (shown in this image) is NOT the correct one!

In order to get the Google Sign-In working with PlayFab, you need to use a Web Client ID. To obtain your Web
Client ID, you must link a Web Application in the Game Ser vices section of the Google Play Console under
the Ser vices and API section.

Then configure your app for the web.


From here, you enter your API Endpoint which can be found in PlayFab:
Look under Settings .
Select the API tab.
Go to the API endpoint field.

Enter this endpoint https://<titleid>.playfabapi.com in the Launch URL field.


Select the Save button.
This will provide you with the proper Client ID .
To obtain your secret key, follow the link to your API Console .

Select your Web Application (Type ).


The Client Secret is at the top.

IMPORTANT
You must change the default callback for Authorized redirect URIs. The proper URI is
https://oauth.playfab.com/oauth2/google . If you do not do this step you will get a mismatch redirect_uri error.

PlayFab Google Sign-In setup


PlayFab has its own process for setting up a Google sign-in. You can do this in your PlayFab developer account. If
you don't have one, you can sign-up here.
To set up Google in PlayFab:
Navigate to the Add-ons section in your dashboard.
Go to the Google Add-On .
From there, select the Install Add-on button.
There are a few things you need to enter into this form:
The Google App Package ID - This is the name of your Android package. For example, our sample uses
com.playfab.gpgexample .
The Google App License Key - While this is a required field, it is not related to the Google Sign-In. This
field is for setting up a Receipt Validation using our Receipt Validation APIs .

NOTE
You can get this License Key from the Google Developer Console under the Ser vices & APIs section. Look for a section
entitled YOUR LICENSE KEY FOR THIS APPLICATION. Copy and paste the Base64-encoded RSA Public Key into this
field.

The Google OAuth Client ID - This is the Web Client ID that you used in the Google Play Games SDK
setup in Unity.
The Google OAuth Client Secret - This is the secret key that you obtained in the last step.

TIP
Be sure to Save Settings !

Adding Google sign-in to your Unity Game


The code to get Google sign-in working is fairly minimal. There is the initialization code, which you will put in
your Start (or anywhere you are initializing or starting up your app).
This can be in different places, depending on the architecture and framework of your game or app. In any case,
the code below will initialize Google Play Games.

NOTE
Make sure that you don't forget the using statements, so that you can use the Google Play Games SDK.

// These using statements are required.


using GooglePlayGames;
using GooglePlayGames.BasicApi;
// The following grants profile access to the Google Play Games SDK.
// Note: If you also want to capture the player's Google email, be sure to add
// .RequestEmail() to the PlayGamesClientConfiguration
PlayGamesClientConfiguration config = new PlayGamesClientConfiguration.Builder()
.AddOauthScope("profile")
.RequestServerAuthCode(false)
.Build();
PlayGamesPlatform.InitializeInstance(config);

// recommended for debugging:


PlayGamesPlatform.DebugLogEnabled = true;

// Activate the Google Play Games platform


PlayGamesPlatform.Activate();

The next set of code, the OnSignInButtonClicked() function shown in the example provided below, is bound to a
Sign In button in the UI in our example.
private void OnSignInButtonClicked()
{
Social.localUser.Authenticate((bool success) => {

if (success)
{

GoogleStatusText.text = "Google Signed In";


var serverAuthCode = PlayGamesPlatform.Instance.GetServerAuthCode();
Debug.Log("Server Auth Code: " + serverAuthCode);

PlayFabClientAPI.LoginWithGoogleAccount(new LoginWithGoogleAccountRequest()
{
TitleId = PlayFabSettings.TitleId,
ServerAuthCode = serverAuthCode,
CreateAccount = true
}, (result) =>
{
GoogleStatusText.text = "Signed In as " + result.PlayFabId;

}, OnPlayFabError);
}
else
{
GoogleStatusText.text = "Google Failed to Authorize your login";
}

});

The OnSignInButtonClicked() code can be a bit overwhelming, so let's break down exactly what is happening:
First, we log in with Social.localUser.Authenticate - This will return a boolean if we are able to successfully
login. Be aware that if you have not added your test account to your app, this will always return False when
testing.
When this happens - important step here - add your test account.
The link will take you to instructions on adding testers to your Google application.

NOTE
This is what will trigger the Google Play Games sign-in dialog to pop-up.

Next, if we have a successful login, we make a call to PlayGamesPlatform.Instance.GetServerAuthCode , and


store it in a variable.
Lastly, we make the LoginWithGoogleAccount call, and pass the AuthCode we just got from Google in as the
ServerAuthCode parameter.

There is a callback which will have the results of your login to PlayFab. At this point, you should see a successful
login in your dashboard!
Hopefully, this guide has helped you. But if you have questions, feel free to ask them in our community forums.
You can download the sample for this tutorial here.
Setting up PlayFab authentication using Kongregate
and HTML5
5/24/2022 • 3 minutes to read • Edit Online

This tutorial shows you the minimal setup required to authenticate your players in PlayFab using Kongregate
and HTML5/JavaScript.

Requirements
A registered Kongregate account.
Familiarity with the Kongregate Developers Guide.
A registered PlayFab title.
Familiarity with Login basics and Best Practices.

Setting up a Kongregate app


Kongregate requires you to upload a preview version of the app, before you gain access to the necessary API
information.
To do this, we need to prepare an index.html file with the following content.

<!doctype html>
<html lang="en-us">
<head></head>
<body>
<h1>Placeholder</h1>
</body>
</html>

Navigate to the Kongregate website:


1. Select the Games tab.
2. Then select the Upload your game button.
A page to set up for a new application will open.
1. Enter the Application Name in the Title field.
2. Then enter a Game Description in the field provided.
3. Select a Categor y .
4. Submit the new app by selecting the Continue button, as indicated in the example provided below.

You will be moved to the Application Upload page.


As a very important first step, make sure to save the URL from your Web Address Bar . This will save you a lot
of time trying to restore access to the application once you close the page.
1. Once this is done, select the prepared index.html file as your Game File .
2. Then set up the screen size.
3. Make sure to accept all the required licenses.
4. Upload your application by selecting the Upload button, as shown in the example provided below.
Once the preview opens, ignore the content and open the api information link.
NOTE
When the API Information page opens, locate the API Key and save it in a safe and easily accessible place for later use.

Configuring PlayFab title


In your PlayFab title Game Manager:
1. Navigate to Add-ons .
2. Then locate and select Kongregate , as shown in the example provided below.
A new page will open, allowing you to set up Kongregate integration.
1. Enter the API Key you acquired in the previous section.
2. Select the Install Kongregate button.

If you receive no error message, then you have configured PlayFab title integration with your Kongregate
application.

Preparing some code


Use the example code shown below to populate the index.html for your game.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns='http://www.w3.org/1999/xhtml'>
<head>
<title>Kongregate Javascript API example</title>
<!-- Import PlayFab API -->
<script src='https://download.playfab.com/PlayFabClientApi.js'></script>
<!-- Import JQuery, required specifically by this example, does not effect either API -->
<script src='https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js'></script>
<!-- Import Kongregate API -->
<script src='https://cdn1.kongregate.com/javascripts/kongregate_api.js'></script>
</head>

<!-- Define elements with IDs to show current state of things and a couple of buttons -->
<body style='background-color:white'>
<span id='init'>Initializing...</span>
<div id='content' style='display:none'>
<div>Kongregate API Loaded!</div>
<div id='username'></div>
<div id='user_id'></div>
<!-- This button will invoke Kongregate Auth Box -->
<button id='login' style='display:none'
onclick='kongregate.services.showRegistrationBox()'>Sign in/register</button>
<!-- This button will invoke PlayFab authentication process -->
<button id='login'
onclick='loginInUsingPlayFab()'>PlayFab Login With Kongregate</button>
</div>

<script type='text/javascript'>

// This function just updates UI, nothing else


function updateFields() {
$('#init').hide();
$('#content').show();

// Visualize Kongregate Auth Data


$('#username').text('Username: ' + kongregate.services.getUsername());
$('#user_id').text('User ID: ' + kongregate.services.getUserId());

// If not authenticated in Kongregate, allow to use Login button


if(kongregate.services.isGuest()) {
$('#login').show();
} else {
$('#login').hide();
}
}

// The function prepares and triggers PlayFab LoginWithKongregate API call


function loginInUsingPlayFab() {
// Setting up playfab title ID
PlayFab.settings.titleId = "159F";

// forming request
var request = {
TitleId: PlayFab.settings.titleId,
AuthTicket: kongregate.services.getGameAuthToken(),
KongregateId : kongregate.services.getUserId(),
CreateAccount: true
};

console.log('logging in');
// Invoke LoginWithKongregate API call and visualize both results (success or failure)
PlayFabClientSDK.LoginWithKongregate(request,
function(result){
$('<div></div>').html('Authenticated via playfab').appendTo('#content')
console.log("success");
console.log("success");
},
function(err){
$('<div></div>').html('Problem occurred: ' + PlayFab.GenerateErrorReport(err)).appendTo('#content')
console.log("failure");
});
}

// The entry point for Kongregate initialization


kongregateAPI.loadAPI(function(){
window.kongregate = kongregateAPI.getAPI();
updateFields();
kongregate.services.addEventListener('login', function(){
updateFields();
});
});
</script>
</body>
</html>

Testing
Remember that URL we asked you to save in a safe and accessible place a little earlier? Use it now to access your
Application Upload page.
1. Select index.html as your Game File .
2. Set up the screen size.
3. Make sure to accept all the required licenses.
4. Upload your application by selecting the Upload button.
Once the preview loads, wait for the Application to obtain the Kongregate User ID and Username .
When that has happened, select the PlayFab Login With Kongregate button.
After a brief pause, you should receive an Authenticated via PlayFab message.
At this point you have successfully logged in using PlayFab and Kongregate!
Setting up PlayFab authentication using Kongregate
and Unity
5/24/2022 • 4 minutes to read • Edit Online

This tutorial shows you the minimal setup required to authenticate your players in PlayFab, using Kongregate
and Unity.

Requirements
A registered Kongregate account.
Familiarity with the Kongregate Developers Guide.
A registered PlayFab title.
A Unity project with PlayFab configured for your title.
Unity WebGL support installed.
Familiarity with Login basics and Best Practices.

Setting up a Kongregate app


Kongregate requires you to upload a preview version of the app, before you gain access to the necessary app
information. Our first step is to prepare an index.html file with the content shown below.

<!doctype html>
<html lang="en-us">
<head></head>
<body>
<h1>Placeholder</h1>
</body>
</html>

Navigate to the Kongregate website.


1. Select the Games tab.
2. Then select the Upload your game button.
A page to set up a new application will open.
1. Make sure to enter the Application Name .
2. Enter a Game Description .
3. Then select a Categor y .
4. Submit the new app by selecting the Continue button.

You will be transferred to the Application Upload page.


First - and most importantly - make sure to save the URL from your Web Address Bar in a safe and easily
accessible place. This will save you a lot of time restoring access to the application once you close the page.
1. Once this is done, select the prepared index.html file as your Game File .
2. Then set up the screen size.
3. Make sure to accept all the required licenses.
4. Finally, upload your application by selecting the Upload button.
Once the preview opens, ignore the content and open the api information link.
When the API Information page opens, locate the API Key and keep it in a safe place that is easily accessible
for later use.

Configuring PlayFab title


In your PlayFab title Game Manager:
1. Select Add-ons from the menu on the left.
2. Locate and select the Kongregate icon.
A new page will open, allowing you to set up Kongregate integration:
1. Enter the API Key you acquired in the previous section.
2. Select the Install Kongregate button.

At ths point, if you do not receive an error message, you have configured PlayFab title integration with your
Kongregate application properly.

Setting up a Unity project


Use this Unity setup checklist:
[OPTIONAL] Install the PlayFab Editor Extensions.
Set up your TitleId in the PlayFabSharedSettings Scriptable Object.
For Unity 5.6+, download the Kongregate Preloader WebGL Template, and place it inside the
Assets/WebGLTemplates folder (2) .
For Unity < 5.6, download the Kongregate Preloader WebGL Template 5.5 and below, and place it inside the
Assets/WebGLTemplates folder (2) .

Now let's create your working scene.


1. For testing purposes, use a screen-scaling canvas with a couple of text labels.

NOTE
We will only need one text label to display debug messages.

2. Create an empty GameObject , and rename it to Kongregate .

This GameObject will contain a KongregateHandler component with a wired text label for debug messages.
The code for the KongregateHandler component is provided below.

// We are specifically interested in importing PlayFab related namespaces


using PlayFab;
using PlayFab.ClientModels;
using UnityEngine;
using UnityEngine.UI;

public class KongregateHandler : MonoBehaviour


{

// Standard unity callback, executed once for the script to start


public void Start()
{
// Utility: show feedback
SetMessage("Loading kongregate api...");

/*
* Important: execute Javascript in the external context to initialize
* Kongregate API, Unity Support and set up callback GameObject and Method.
* In this case, callback is set to a GameObject called Kongregate and a
* method called OnKongregateAPILoaded, which we define later in this class.
* Once Kongregate API is initialized, Unity will locate this object by name
* ("Kongregate") and execute a method "OnKongregateAPILoaded" passing in user
* info string as an argument.
*/
Application.ExternalEval(
"if(typeof(kongregateUnitySupport) != 'undefined'){" +
" kongregateUnitySupport.initAPI('Kongregate', 'OnKongregateAPILoaded');" +
"} else {" +
" console.error('No unity support!');" +
"};"
);
}

/*
* Executed once Kongregate API is ready. This method is invoked by KongregateAPI
* and receives a structured text with multiple pieces of data you must parse manually.
* The userInfo string parameter has the following structure: 'user_identifier|user_name|auth_token'
*/
public void OnKongregateAPILoaded(string userInfo)
{
SetMessage("Received user info! Logging though playfab...");

// We split userInfo string using '|' character to acquire auth token and Kongregate ID.
var userInfoArray = userInfo.Split('|');
var authTicket = userInfoArray[2];
var kongregateId = userInfoArray[0];

LogToBrowser("Auth Token: " + authTicket);


LogToBrowser("Kongregate Id: " + kongregateId);
LogToBrowser("Kongregate Id: " + kongregateId);

/*
* We then execute PlayFab API call called LoginWithKongregate.
* LoginWithKongregate requires KongregateID and AuthTicket.
* We also pass CreateAccount flag, to automatically create player account.
*/
PlayFabClientAPI.LoginWithKongregate(new LoginWithKongregateRequest
{
KongregateId = kongregateId,
AuthTicket = authTicket,
CreateAccount = true
}, OnLoggedIn, OnFailed);
}

/*
* The rest of the code serves as a utility to process results, log debug statements
* and display them using Text message label.
*/

private void OnLoggedIn(LoginResult obj)


{
SetMessage("Logged in through PlayFab!");
}
private void OnFailed(PlayFabError error)
{
SetMessage("Failed to login in with PlayFab: " + error.GenerateErrorReport());
}

private void SetMessage(string message)


{
InfoLabel.text = message;
}

private void LogToBrowser(string message)


{
Application.ExternalEval(string.Format("console.log('{0}')", message));
}

public Text InfoLabel;


}

Testing
The only way you can truly test the integration is by uploading your prototype to Kongregate.
1. Open the Build window and make sure WebGL is selected from your menu.
2. Then open the Player Settings by selecting the button.
Inside the Player Settings screen, locate the Settings for WebGL build:
1. Verify that you have the size set up correctly.
2. Then select the Kongregate Preloader Template .

Build the application and open the Build folder.


You will end up with index.html and a bunch of other files (depending on Unity version).
Take all the files except index.html and place them inside a zip archive, as shown in the example provided
below.
Use the URL you saved earlier to access your Application Upload page.
1. Select index.html as your Game File .
2. Then select the zip archive as Additional files .
Accept the licenses and upload.

Once the preview opens, you should be able to see your game live as the message changes.
At completion, the message should indicate successful login through PlayFab.
At this point, you have successfully integrated PlayFab and Kongregate.
Setting up PlayFab authentication in Phaser.io
5/24/2022 • 2 minutes to read • Edit Online

Phaser.io is a desktop and mobile HTML5 game framework that PlayFab now supports in our Javascript SDK.
Phaser.io supports plugins, so we at PlayFab thought that it would be useful for the Phaser.io community to have
a powerful back end system that works as a plugin to the Phaser.io engine.
This tutorial guides you through the procedure for setting up Phaser.io, and getting started with PlayFab within
Phaser.io.

Requirements
Knowledge of JavaScript.
Knowledge of setting up a web server.
General understanding of Phaser.io (a plus!).

Setting up a web server using MAMP


To serve HTML pages to your browser, you will need a web server. We use MAMP/MAMP Pro, but you can use
whatever you are most comfortable with.
To begin:
Set up a website via Mamp/Mamp Pro, or your webserver of choice.
Create an Index.html file in the root of your website folder.

NOTE
Alternately, you can refer to the Running an HTTP server for testing tutorial for information on how to set one up.

Setting up Phaser
The first step is to download Phaser from Phaser.io and set it up. For this tutorial, we advise you to just
download the min.js file.
Create a folder in your website root called js .
Download Phaser min.js and save it to your /js folder in the website root.
Setup code
Start by copying and pasting the code that follows into Index.html .

<!doctype html>
<html class="no-js" lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">

<link rel="apple-touch-icon" href="apple-touch-icon.png">

<script src="https://code.jquery.com/jquery-1.12.0.min.js"></script>
<script src="js/phaser.min.js"></script>
</head>
<body>
Hello World!
</body>
</html>

You should see a page similar to the one in the image below, with Hello World! in the top left corner and the
rest of the page blank.

Next Steps
Add a new file in your /js folder called main.js .
Add the code shown below to main.js .
var game = new Phaser.Game(800, 600, Phaser.AUTO, '', { preload: preload, create: create, update: update });

function preload() {
}

function create() {
}

function update() {
}

You should now see that Phaser.io has initialized a blank canvas (like that shown in the example provided below).
This means that your Phaser.io installation is completed.

Adding PlayFab and Phaser plugin


The PlayFab Javascript SDK will now auto-detect if you have Phaser loaded on the webpage, and inject itself into
it as a Phaser plugin.
There are only two lines of code needed to make this happen:
1. Add the script tag to load PlayFab just after loading Phaser.

2. Copy this code into the create() method of main.js

function create() {
game.PlayFab = game.plugins.add(Phaser.Plugin.PlayFab);
}

Making your first API call


Now that you have PlayFab installed as a plugin to Phaser, you can set your PlayFab titleId and make API calls.
The code presented below shows you how to log in a player.
game.PlayFab.settings.titleId = "D6EC"; //Your title Id from playfab goes here.
game.PlayFab.ClientApi.LoginWithCustomID({
"CustomId":"SomeUniqueIdForYourPlayer",
"CreateAccount":true
}, function(result){
console.log("LoggedIn as " + result.PlayFabId);
});
Setting up PlayFab authentication using Steam and
Unity
5/24/2022 • 2 minutes to read • Edit Online

This tutorial guides you through the steps for logging into PlayFab using Steam through SteamWorks and Unity.

Prerequisites
Before beginning, you should have:
A Unity project with an imported PlayFab SDK, and a configured title ID.
A Steam Application with:
The AppID already set up. The AppID is usually acquired through the Steam Direct (Formerly
Greenlight) process.
A Steam Publisher Web API Key. Follow Creating a Publisher Web API Key in the Steamworks
documentation to generate a publisher key.
Familiarity with Login basics and Best Practices.

Setting up a PlayFab title


To enable support for Steam authorization, PlayFab requires you to enable the Steam add-on.
Go to your Game Manager page:
1. Select the Add-ons menu item.
2. In the list of available Add-ons , locate Steam and select the title link:
1. Enter your App ID .
2. Enter the Web API Key .
3. Then select Install Steam .
This concludes setting up a PlayFab title for Steam integration.

Setting up a Unity project


Start by downloading the latest release of Steamworks.NET from the Releases page.
Get the Unity Package version of the release, and import it into the project.
Once you import the package, close Unity.
Navigate to the Project root folder.
Locate the steam_appid.txt file.
Open the file and replace the App ID value with your own.

Re-open Unity and create a new scene.


Inside that scene create a new gameobject called Steam :
1. Add a SteamManager component to the gameobject . This component is part of Steamworks.Net.
2. Create and add a SteamScript component to the gameobject .

The following example shows the code for the SteamScript component.
(Thanks to Dylan Hunt for this example.)
// Import all the necessary namespaces
using System;
using System.Text;
using PlayFab;
using PlayFab.ClientModels;
using Steamworks;
using UnityEngine;

public class SteamScript : MonoBehaviour {


//This method returns
public string GetSteamAuthTicket() {
byte[] ticketBlob = new byte[1024];
uint ticketSize;

// Retrieve ticket; hTicket should be a field in the class so you can use it to cancel the ticket
later
// When you pass an object, the object can be modified by the callee. This function modifies the
byte array you've passed to it.
HAuthTicket hTicket = SteamUser.GetAuthSessionTicket(ticketBlob, ticketBlob.Length, out ticketSize);

// Resize the buffer to actual length


Array.Resize(ref ticketBlob, (int)ticketSize);

// Convert bytes to string


StringBuilder sb = new StringBuilder();
foreach (byte b in ticketBlob) {
sb.AppendFormat("{0:x2}", b);
}
return sb.ToString();
}

public void OnGUI() {


if (GUILayout.Button("Log In")) {
if (SteamManager.Initialized) {
// Execute PlayFab API call to log in with steam ticket
PlayFabClientAPI.LoginWithSteam(new LoginWithSteamRequest {
CreateAccount = true,
SteamTicket = GetSteamAuthTicket()
}, OnComplete,OnFailed);
}
}
}

// Utility callbacks to log the result


private void OnComplete(LoginResult obj) {
Debug.Log("Success!");
}

private void OnFailed(PlayFabError error) {


Debug.Log("Failed: " + error.GenerateErrorReport());
}
}

Testing
You may test right inside the editor:
1. Run the scene and select the Log In button.
2. The console message should appear after a moment, indicating the authentication result Success! .
Setting up PlayFab authentication using Twitch and
HTML5
5/24/2022 • 3 minutes to read • Edit Online

This tutorial has been designed to guide you through the process of PlayFab authentication, using Twitch and
HTML5/JavaScript.

Requirements
Prior to beginning, you should have:
A Twitch Account for testing.
A Registered PlayFab title.
Familiarity with Login basics and Best Practices.
At the minimum, a server with a valid domain name to serve static HTML files.

NOTE
Consult the Running an HTTP server for testing tutorial for information on how to set up a server with a valid domain
name.

Server and domain


This tutorial requires a web server, in order to follow the instructions. If you do not have a registered remote
web server yet, please follow our Running an HTTP server for testing tutorial, for information on how to run a
local web server.

NOTE
Throughout this tutorial, we will assume your domain is http://localhost/.

Registering a Twitch application


Start by navigating to the Twitch website, and verifying that you are logged in.
1. Navigate to the Account drop-down.
2. Select Settings from the menu provided.
On the Settings page, select Connections (1) , as shown below.

At the very bottom of the page, select the Register your application (1) button, as shown below.

A page will open that lets you configure a new app.


1. Fill in the Name of the Application .
2. Enter the Redirect URL .
3. Enter the Application Categor y .
4. Then agree to the Twitch terms, and select the Register button.
IMPORTANT
When testing using a local web server, Twitch allows you to use http://localhost as a redirect URL. Make sure to include
the leading slash /. Without a leading slash, Twitch will fail to recognize the localhost URL.

Once the application is registered, the page will be updated and reveal the Client ID for your application.

NOTE
Keep this Client ID in a safe and easily accessible place, as you will be using it later to configure your PlayFab title.
Configuring a PlayFab title
Once you acquire your Twitch Client ID, you may enable and configure a Twitch Add-on for your PlayFab title.
1. On your PlayFab Title screen, go to the menu and select the Add-ons item.
2. Then select the Twitch icon link.

On the Twitch page:


A Settings page will open for the Twitch Add-on .
Enter your Twitch Client ID .
Select the Install Twitch button.
Take a moment to verify that the add-on was installed, and that no errors have occurred. This concludes
configuring the PlayFab title.

Testing
Use the following HTML file to test PlayFab authentication using Twitch.
Make sure to replace TWITCH_CLIENT_ID_GOES_HERE and PLAYFAB_TITLE_ID_GOES_HERE with your own values.
<!DOCTYPE html>
<html>
<head>
<!-- Include JQuery - dependency of Twitch JS SDK -->
<script src="//code.jquery.com/jquery.min.js"></script>
<!-- Include Twitch SDK -->
<script src="https://ttv-api.s3.amazonaws.com/twitch.min.js"></script>
<!-- Include PlayFab SDK -->
<script src="https://download.playfab.com/PlayFabClientApi.js"></script>
</head>
<body>
<p>Twitch Auth Example</p>
<button onclick="login()">Login With Twitch</button>
<script>
// Establish Twitch Auth Callback (invoked when logged in with Twitch)
Twitch.events.addListener('auth.login', function() {
logLine("Logged in with Twitch!");
// Invoke login with PlayFab code and pass the token
loginWithPlayFab(Twitch.getToken());
});

// Run Twitch SDK initialization


Twitch.init({clientId: 'TWITCH_CLIENT_ID_GOES_HERE'}, function(error, status) {
logLine("Twitch SDK Initialized");
});

// This method is invoked when you press the button

function login() {
logLine("Logging in via Twitch...");
Twitch.login({
scope: ['user_read', 'channel_read']
});
}

function loginWithPlayFab(accessToken){
logLine("Logging in via PlayFab...");

// When given accessToken, make call to LoginWithTwitch API Call


// Make sure to use your own PlayFab Title ID
PlayFabClientSDK.LoginWithTwitch({
AccessToken: accessToken,
TitleId: "PLAYFAB_TITLE_ID_GOES_HERE",
CreateAccount: true
}, onPlayFabResponse);
}

// Handles response from playfab.


function onPlayFabResponse(response, error) {
if (response)
logLine("Response: " + JSON.stringify(response));
if (error)
logLine("Error: " + JSON.stringify(error));
}

function logLine(message) {
console.log(message);
var textnode = document.createTextNode(message);
document.body.appendChild(textnode);
var br = document.createElement("br");
document.body.appendChild(br);
}
</script>
</body>
</html>
1. Request the following file from your server, using the domain you set up during the Twitch application
configuration http://localhost in our case.
2. Once the page opens, wait for the message indicating that the Twitch SDK was initialized.
3. Then select the Login with Twitch button.
4. Follow any Twitch instructions in the pop-up window, and watch the output.

IMPORTANT
If you already have a Twitch auth session going when reaching the page, it is possible for callbacks to fire in a different,
unexpected order. This case is shown in the screenshot shown below. However, you should make sure that only Logging
in via PlayFab follows after Logged in with Twitch . This indicates that the token was received or restored from the
local storage, and we do not have to wait for the Twitch SDK to start signing in to PlayFab.

If PlayFab manages to acquire a SessionTicket , you have successfully integrated Twitch authentication with
your PlayFab app.
Setting up PlayFab authentication using Universal
Windows Platform
5/24/2022 • 9 minutes to read • Edit Online

This tutorial guides you through the procedure for PlayFab authentication using the Universal Windows
Platform (UWP).

IMPORTANT
This procedure serves as a very basic introduction on how you can obtain all entities, and commit authentication via
Windows Hello and PlayFab. For a more sophisticated example of Windows Hello and PlayFab authentication, consider our
UWPExample project.

Requirements
Follow the MSDN "Get Set Up" Guide to prepare Windows and Visual Studio for UWP development.
Have a registered PlayFab title.
Be familiar with Login basics and Best Practices.

NOTE
it is very important that you use the Windows 10 operating system, are logged in with a verified Microsoft account, and
have configured an access interface such as PIN. If these requirements are not met, the app will fail without any useful
explanation of why.

Preparing a Visual Studio project


Start Visual Studio and create a new project.
1. Under Templates , select Windows Universal .
2. Then select the Blank App (Universal Windows) type.
3. Name it GettingStar tedPlayfabUWP .
4. Select the OK button to submit.
1. Select the Target Version and the Minimum Version that match your Project .
2. Select the OK button.

Once the Project is created, add the PlayFab SDK using the NuGet Package Manager .
1. First, select the Tools tab.
2. In the drop-down menu, select NuGet Package Manager .
3. Then select Manage NuGet Packages for Solution .
In the NuGet Manager window:
1. Select Browse and search for the PlayFabAllSDK package.
2. Select your target Project .
3. Then select the Install button.

Once finished, your basic project setup is complete. In the next section we will modify 2 classes that should be
automatically generated on project creation:
1. App
2. MainPage
Implementation
App.xaml.cs
This class will just set up our PlayFab SDK by setting a proper title ID. Do not forget to replace the title ID with
your own.

using System;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;

namespace GettingStartedPlayfabUWP
{
// This class is generated upon project creation.
// While template on it's own contains a lot of xml comments, we are only interested in lines 17 and 27
sealed partial class App : Application
{

// Replace PLAYFAB_TITLE_ID with your own


public const string PlayfabTitleId = "PLAYFAB_TITLE_ID";

/// <summary>
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary>
public App()
{

// This is the only line of functional code we need to add to this class.
PlayFab.PlayFabSettings.TitleId = PlayfabTitleId;

this.InitializeComponent();
this.Suspending += OnSuspending;
}

/// <summary>
/// Invoked when the application is launched normally by the end user. Other entry points
/// will be used such as when the application is launched to open a specific file.
/// </summary>
/// <param name="e">Details about the launch request and process.</param>
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;

// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (rootFrame == null)
{
// Create a Frame to act as the navigation context and navigate to the first page
rootFrame = new Frame();

rootFrame.NavigationFailed += OnNavigationFailed;

if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
//TODO: Load state from previously suspended application
}

// Place the frame in the current Window


Window.Current.Content = rootFrame;
}

if (e.PrelaunchActivated == false)
{
if (rootFrame.Content == null)
if (rootFrame.Content == null)
{
// When the navigation stack isn't restored navigate to the first page,
// configuring the new page by passing required information as a navigation
// parameter
rootFrame.Navigate(typeof(MainPage), e.Arguments);
}
// Ensure the current window is active
Window.Current.Activate();
}
}

/// <summary>
/// Invoked when Navigation to a certain page fails
/// </summary>
/// <param name="sender">The Frame which failed navigation</param>
/// <param name="e">Details about the navigation failure</param>
void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
{
throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
}

/// <summary>
/// Invoked when application execution is being suspended. Application state is saved
/// without knowing whether the application will be terminated or resumed with the contents
/// of memory still intact.
/// </summary>
/// <param name="sender">The source of the suspend request.</param>
/// <param name="e">Details about the suspend request.</param>
private void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
//TODO: Save application state and stop any background activity
deferral.Complete();
}
}
}

MainPage.xaml
This file contains the layout for our main page. This is a super trivial layout with 2 buttons, and a text input
combined in a vertically oriented grid.
The buttons are bound to specific methods, and the textbox is accessible via its name UsernameInput .

<Page
x:Class="GettingStartedPlayfabUWP.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:GettingStartedPlayfabUWP"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">


<StackPanel Margin="0,10,10,0">
<TextBox x:Name="UsernameInput" TextWrapping="Wrap" Text="" PlaceholderText="Username..."/>
<Button x:Name="RegisterButton" Content="Register With Hello" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" Click="RegisterRequest"/>
<Button x:Name="LoginButton" Content="Sign In With Hello" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" Click="LogInRequest"/>
</StackPanel>
</Grid>
</Page>

MainPage.xaml.cs
This is the functional class for the main page and it is the heart of the example. Please refer to the code
comments, and review the different methods that are designed to walk you through PlayFab+Hello register and
login.
The easiest approach to start learning the code is to review the methods that are triggered by the corresponding
buttons:
RegisterRequest
LogInRequest .

using System;
using System.Linq;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Networking.Connectivity;
using Windows.Security.Credentials;
using Windows.Security.Cryptography;
using Windows.Security.Cryptography.Core;
using Windows.Storage.Streams;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using PlayFab;
using PlayFab.ClientModels;

namespace GettingStartedPlayfabUWP
{
public sealed partial class MainPage : Page
{
// Shortcut to get current value of UsernameInput
public string Username => UsernameInput.Text;

public MainPage()
{
this.InitializeComponent();
}

/// <summary>
/// This method is invoked when you select the Register button
/// This method illustrates the flow for Registration process.
/// We operate on 2 entities:
/// - User Credentials of type KeyCredential
/// - Public Key of type String
/// We first check if user with this id already has Credentials. If so, we redirect to login
procedure.
/// Then we create new User Credentials. Check CreateKeyCredential for implementation details
/// Then we get Base64 encoded Public Key using the new User Credentials. Check GetPublicKeyBase64
for implementation details
/// Then we execute RegisterWithHello api call call. Check CallPlayFabRegisterWithHello for
implementation details
/// </summary>
private async void RegisterRequest(object sender, RoutedEventArgs e)
{
// Check if the user already exists and if so log them in.
KeyCredentialRetrievalResult retrieveResult = await KeyCredentialManager.OpenAsync(Username);
if (retrieveResult.Status == KeyCredentialStatus.Success)
{
// Redirect to login procedure
LogInRequest(sender, e);
return;
}

// Create a new KeyCredential for the user on the device.


var credential = await CreateKeyCredential(Username);
if (credential == null) return;
var publicKey = await GetPublicKeyBase64(credential);
if (string.IsNullOrEmpty(publicKey)) return;
// Include the name of the current device for the benefit of the user.
// The server could support a Web interface that shows the user all the devices they
// have signed in from and revoke access from devices they have lost.

var registerResponse = await CallPlayFabRegisterWithHello(publicKey, Username);

await ShowMessage("Registered and signed in with Session Ticket " +


registerResponse.Result.SessionTicket);
}

//
/// <summary>
/// This method is invoked when you select the Log In button
/// This method shows entities flow during the sign in process.
/// We have 4 different entities:
/// - User Credentials of type KeyCredential
/// - Public Key Hint of type String
/// - Challenge of type String
/// - SignedChallenge of type String
///
/// We first acquire the User Credentials. We do it based on Username. Check GetUserCredentials
method for implementation details
/// Next, we get Public Key Hint based on those credentials. Check GetPublicKeyHint for
implementation details.
/// Next we request a Challenge from PlayFab. Check GetPlayFabHelloChallenge for implementation
details
/// Next we sign the Challenge using User Credentials, so we obtain Signed Challenge. Check
GetPlayFabHelloChallenge for implementation details
/// Finally we use Signed Challenge and Public Key Hint to log into PlayFab. Check
CallPlayFabLoginWithHello for implementation details
/// </summary>
private async void LogInRequest(object sender, RoutedEventArgs e)
{
// Get credentials based on current Username.
var credentials = await GetUserCredentials(Username);
if (credentials == null) return;

// Credentials will give us Public Key. We use it to construct Public Key Hint, which is first
important entity for PlayFab+UWP authentication.
var publicKeyHint = GetPublicKeyHintBase64(credentials);
if (string.IsNullOrEmpty(publicKeyHint)) return;

// Get PlayFab Challenge to sign for Windows Hello.


var challenge = await GetPlayFabHelloChallenge(publicKeyHint);
if (string.IsNullOrEmpty(challenge)) return;

// Request user to sign the challenge.


var signedChallenge = await RequestUserSignChallenge(credentials, challenge);
if (string.IsNullOrEmpty(signedChallenge)) return;

// Send the signature back to the server to confirm our identity.


// The publicKeyHint tells the server which public key to use to verify the signature.
var result = await CallPlayFabLoginWithHello(publicKeyHint, signedChallenge);
if (result == null) return;

// Report the result.


await ShowMessage("Signed in with Session Ticket " + result.Result.SessionTicket);
}

public async Task<string> GetPublicKeyBase64(KeyCredential userCredential)


{

IBuffer publicKey = userCredential.RetrievePublicKey();

if (publicKey == null)
{
await ShowMessage("Failed to get public key for credential");
return null;
}

return CryptographicBuffer.EncodeToBase64String(publicKey);
}

public string GetPublicKeyHintBase64(KeyCredential userCredential)


{
HashAlgorithmProvider hashProvider =
HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);
var publicKey = userCredential.RetrievePublicKey();
IBuffer publicKeyHash = hashProvider.HashData(publicKey);
return CryptographicBuffer.EncodeToBase64String(publicKeyHash);
}

public async Task<KeyCredential> GetUserCredentials(string userId)


{
// Open credential based on our Username and make sure it is successful
KeyCredentialRetrievalResult retrieveResult = await KeyCredentialManager.OpenAsync(userId);

if (retrieveResult.Status != KeyCredentialStatus.Success)
{
await ShowMessage("Error: Unable to open credentials! " + retrieveResult.Status);
return null;
}

return retrieveResult.Credential;
}

public async Task<string> GetPlayFabHelloChallenge(string publicKeyHint)


{
// Request challenge from PlayFab and make sure response has no errors
var challengeResponse = await PlayFab.PlayFabClientAPI.GetWindowsHelloChallengeAsync(new
GetWindowsHelloChallengeRequest
{
PublicKeyHint = publicKeyHint,
TitleId = PlayFab.PlayFabSettings.TitleId
});

if (challengeResponse.Error != null)
{
await ShowMessage($"Error during getting challenge: {challengeResponse.Error.Error}");
return null;
}

return challengeResponse.Result.Challenge;

public async Task<string> RequestUserSignChallenge(KeyCredential credentials, string challenge)


{
IBuffer challengeBuffer = CryptographicBuffer.DecodeFromBase64String(challenge);
KeyCredentialOperationResult opResult = await credentials.RequestSignAsync(challengeBuffer);

if (opResult.Status != KeyCredentialStatus.Success)
{
await ShowMessage("Failed sign the challenge string: " + opResult.Status);
return null;
}

return CryptographicBuffer.EncodeToBase64String(opResult.Result);
}

public async Task<PlayFabResult<LoginResult>> CallPlayFabLoginWithHello(string publicKeyHint, string


signedChallenge)
{
var loginResponse = await PlayFab.PlayFabClientAPI.LoginWithWindowsHelloAsync(new
LoginWithWindowsHelloRequest
LoginWithWindowsHelloRequest
{
ChallengeSignature = signedChallenge,
PublicKeyHint = publicKeyHint
});

if (loginResponse.Error != null)
{
await ShowMessage($"Failed to log in: {loginResponse.Error.Error}");
return null;
}

return loginResponse;
}

public IAsyncOperation<IUICommand> ShowMessage(string messageString)


{
MessageDialog message = new MessageDialog($"{messageString}");
return message.ShowAsync();
}

public async Task<PlayFabResult<LoginResult>> CallPlayFabRegisterWithHello(string publicKey, string


username)
{
var hostNames = NetworkInformation.GetHostNames();
var localName = hostNames.FirstOrDefault(name => name.DisplayName.Contains(".local"));
string computerName = localName.DisplayName.Replace(".local", "");

var registerResult = await PlayFab.PlayFabClientAPI.RegisterWithWindowsHelloAsync(new


RegisterWithWindowsHelloRequest
{
DeviceName = computerName,
PublicKey = publicKey,
UserName = username
});

if (registerResult.Error != null)
{
await ShowMessage(registerResult.Error.GenerateErrorReport());
return null;
}

return registerResult;
}

public async Task<KeyCredential> CreateKeyCredential(string username)


{
KeyCredentialRetrievalResult keyCreationResult = await
KeyCredentialManager.RequestCreateAsync(username, KeyCredentialCreationOption.ReplaceExisting);
if (keyCreationResult.Status != KeyCredentialStatus.Success)
{
// User has authenticated with Windows Hello and the key credential is created.
await ShowMessage("Failed to create key credential: " + keyCreationResult.Status);
return null;
}

return keyCreationResult.Credential;
}

Testing
To run the application:
1. Enter your username.
2. Select the Register With Hello button.

Follow the instruction that Windows offers for authentication.


1. Once your identity is confirmed, you will see the confirmation message saying that the account was
Registered and signed in .
2. With a Session Ticket .

1. Select the Sign in With Hello button.


Follow the instruction that Windows offers for authentication.
1. Once your identity is confirmed, you will see the confirmation message saying that the account is Signed in .
2. With a Session Ticket .

At this point you have successfully integrated PlayFab into your UWP application.
Setup Sign In with Apple for PlayFab
5/24/2022 • 2 minutes to read • Edit Online

This guide covers the series of steps needed to setup your PlayFab applications to take advantage of Sign in with
Apple.

Setup your Application Identifier


Before you can use Sign in with Apple in your applications, you'll need to address some setup steps in the
Certificates, Identifiers & Profiles section of Apple's developer portal.
1. Sign in to your Apple Developer Program account.
2. Select Cer tificates, Identifiers & Profiles .
3. In the Identifiers pane, select your Application Identifier, or select (+) to create a new identifier.

NOTE
If you are creating a new identifier, select App IDs as the new identifier type.

4. Scroll through the list of capabilities and select Sign in with Apple .
5. Press Continue or Save on the Sign in with Apple setup popup.
6. Ensure you fully create and update your application identifier.
Save the identifier where you can access it easily. You will use in the next set of steps.

IMPORTANT
PlayFab only supports Sign in with Apple from IoS or MacOS Titles.

Setup the Apple Add-on in PlayFab


To setup the Apple Add-on in PlayFab:
1. Log in to the PlayFab Game Manager.
2. Select your title from the My Studios and Titles page.
3. In the Add-ons pane, select the Apple platform.
4. To install the Apple add-on, select Install Apple .
5. Set the iOS App Bundle ID to the App ID that your retrieved in the previous section.

NOTE
At this point you need to choose whether you want to ignore the expiration date for identity tokens.

Your options are:


Ignore expiration dates: This provides a less secure, but better user experience.
Honor expiration dates: This provides a more secure experience at the expense of potentially causing the user
sign in multiple times. Apple identity tokens currently expire after 10 minutes after which your Title must
require the user to sign in again to obtain a new one.
6. Set the Ignore expiration date for identity tokens as appropriate for your chosen user experience.

TIP
If you choose to ignore the expiration date for identity tokens, your Title should store the identity token that it obtains
from Apple locally. The identity token will be reused to log in each time.
Integrating the Universal Windows platform with
PlayFab
5/24/2022 • 3 minutes to read • Edit Online

This tutorial takes you through three key points of integration between PlayFab and the Universal Windows
Platform (UWP).

NOTE
We have created a GitHub repository with sample code to illustrate how to integrate Universal Windows Platform with
PlayFab.

Integrating the Universal Windows Platform (UWP) with PlayFab is very straightforward. There are really only
three things you need to worry about:
1. Linking a Windows Hello account to your PlayFab account.
2. Logging in the player via Windows Hello.
3. Validating a purchase made from the Windows store.
Let's take these three topics in order.

Linking a Windows Hello account to your PlayFab account


There are two ways you can link a Windows Hello account to your PlayFab account:
1. You can either create a new PlayFab account using your Windows Hello credentials.
2. You can link Windows Hello credentials to your existing PlayFab account.
Which one you use depends on whether or not Windows Hello is your primary authentication.
Creating a new account with Windows credentials
Before you can begin this process, you need to ask the user for their username in Windows.
Then you can follow these steps:
1. Call KeyCredentialManager.RequestCreateAsync, to generate a new public key for this user.
2. Call CryptographicBuffer.EncodeToBase64String, to convert the IBuffer from above to a string.
3. Call PlayFabClientAPI.RegisterWithWindowsHello, with the following required parameters:
The Windows username.
The Base 64-encoded public key from above.
4. Assuming the register was successful, the player will now be logged in. You will get back a session token that
you can use to authenticate the player with all other PlayFab APIs.
5. Also, you can now use HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256) to create a
hash provider, and hash the public key by calling hashProvider.HashData(publicKey).
6. Convert the hashed public key to a Base 64-encoded string
(CryptographicBuffer.EncodeToBase64String(publicKeyHash)) and store this string and the username in the
application settings. (ApplicationData.Current.LocalSettings.Values["publicKeyHint"]). This public key hint is
used to log back in.
7. The username should also be stored in the user's local settings, as well for simpler login.
Linking Windows credentials to an existing PlayFab account
The process for linking Windows credentials to an existing PlayFab account is very similar. The differences are:
1. First, you must already be logged into a PlayFab account. Typically this is done anonymously, using an
insecure, device ID.
2. Then, follow the steps in the previous section, but use LinkWindowsHello instead of
RegisterWithWindowsHello .
3. Now the user can log in with Windows credentials in the future and access or recover their PlayFab account.

Logging in the Player via Windows Hello


Once you have linked Windows Hello credentials to a PlayFab account, you can log in with those credentials. You
will need the public key hint, and the Windows username.
Follow these steps:
1. Call PlayFabClientAPI.GetWindowsHelloChallengeAsync to create a signing challenge.
2. Call CryptographicBuffer.DecodeFromBase64String to create an IBuffer for the KeyCredentialManager to have
the user sign.
3. Call var retrieveResult = await KeyCredentialManager.OpenAsync(userId) to create a key signing service.
4. Get the credential for this user: var userCredential = retrieveResult.Credential .
5. Call await userCredential.RequestSignAsync(challengeBuffer) to have Windows request that the user sign the
server's challenge for this user.
6. Finally, call PlayFabClientAPI.LoginWithWindowsHello to complete the process and log in the player.
7. Assuming the login was successful, the player is now logged in. You will get back a session token that you
can use to authenticate the player with all other PlayFab APIs.

Making a purchase via Windows store


Making a purchase via the Windows store is similar to the purchase process via iOS or Android. There are two
stages:
1. Setting up the store in the first place.
2. Then making the purchase.
Setting up the Store
Microsoft has published several documents describing this process. For example:
Setting up the in-app purchase in the Windows Store
You must also be sure to set up a matching item in the PlayFab catalog, with the same product ID.
Making the purchase
Once you have set up the items in the store, you can enable the in-app purchase in your app.
1. Make the purchase in the application, and be sure to request a receipt.
This document explains the process: making in-app purchases with UWP.
2. You will get back a receipt.
You can find more information on receipts here.
3. Call PlayFabClientAPI.ValidateWindowsStoreReceipt to validate the receipt. This will automatically credit the
player's inventory in PlayFab with the item they just purchased.

Further questions
If you have further questions, please post in our forums.
We'd also love to hear from you with any feedback on integrating your game with the Universal Windows
Platform!
Azure Active Directory Authentication for Playfab
Game Manager
5/24/2022 • 2 minutes to read • Edit Online

PlayFab now supports three methods of user authentication. The first two are the original PlayFab user
authentication system and SAML. The third is now Azure Active Directory (AAD).
To Create a New AAD User
1. Navigate to your studio's users section.

2. Select Add User and select Microsoft as the authentication provider.

3. Assign roles as normal and send invite. The user will have the option to login with microsoft.
Sign-Up with AAD
You can start a new PlayFab studio with AAD.
1. Navigate to https://developer.playfab.com/en-US/sign-up.
2. Select Sign in with Microsoft .
PlayFab AAD Limitations
AAD authentication is functional for individual users, including AAD token exchange for programmatic
authentication. It does not support groups or graph.
Automation with PlayFab
5/24/2022 • 2 minutes to read • Edit Online

Automation is an important engineering process that greatly improves your efficiency. With PlayFab, you can
leverage features such as Actions and Rules, CloudScript, Custom Tags, and Scheduled Tasks. These features
provide means to automate processes according to a set of criteria, for example the scenario "upon receiving a
new player sign up, automatically send an email to their account and fire telemetry PlayStream events." You
have a lot of room to customize your automation, for example with Custom Tags you can enable scenarios such
as "when a player purchases an item that belongs to BFF, a custom game category that is tagged, give all their
friends 10 coins for free."
Please refer to individual feature pages under Automation for more detailed conceptual documentation and
tutorials.
CloudScript
5/24/2022 • 2 minutes to read • Edit Online

CloudScript is one of PlayFab’s most versatile features. It allows client code to request execution of any custom
server-side functionality you can implement, and it can be used in conjunction with virtually anything.
CloudScript enables you to build server-side logic and functionality that scales to meet your demand, without
worrying about servers or infrastructure. You can create CloudScript functions that can only be accessed via
your service, to prevent any tampering attempts from clients.
For example, you can have a client request a “daily reward” from your game, and trust your server-side
validation to prevent granting the reward twice.

Links
To get started with latest CloudScript release, CloudScript using Azure Functions, check out our CloudScript
Functions quickstart guide.
If you're still using the CloudScript (Legacy) offering and haven't migrated to CloudScript using Azure Functions
yet, you can find the old documentation here:
CloudScript (Legacy) quickstart
CloudScript (Legacy) tutorials
CloudScript (Legacy) quickstart
5/24/2022 • 2 minutes to read • Edit Online

CloudScript offers a fast, secure and scalable alternative to dedicated servers. Your custom JavaScript lives and
executes directly on PlayFab machines.

NOTE
CloudScript using Azure Functions supports more languages and has improved debugging workflows.

From here, your code can be called directly by your game clients - or indirectly via PlayStream actions.
Additionally, CloudScript (Legacy) methods have full access to PlayFab's Server API set.
This quickstart covers uploading and managing your CloudScript files in the PlayFab Game Manager.

NOTE
The Writing custom CloudScript tutorial covers writing the CloudScript (Legacy) code itself.

Please note the following when reading this:


You should be familiar with the basics of PlayFab.
The C# samples shown correspond to using the PlayFab Unity SDK.
JavaScript samples correspond to using the PlayFab CloudScript (Legacy) service.

Your first CloudScript (Legacy) revision


After creating a title, PlayFab automatically includes an example script as your first revision. This revision
includes a number of methods that you can use for learning and testing CloudScript (Legacy).
To see these functions:
Open Game Manager.
Select your title.
Select Automation on the left side bar.
You should see a number of CloudScript (Legacy) methods - such as HelloWorld , which logs the message
Hello PL AYERID - where PL AYERID is the current player's PlayFab ID.
Uploading your own revisions
You can upload your own custom methods via the Game Manager. Each file you upload will create a new
revision. During the upload, the PlayFab service runs a simple LINT check over your CloudScript (Legacy) for
syntax errors.
If it finds an error:
An error message will be displayed.
Fix the error, and select SUBMIT again.
By default, new uploads must be deployed by selecting the DEPLOY REVISION # TO LIVE link. This
enables you to update or roll back to/from multiple versions of CloudScript (Legacy).
The first time you press the orange UPLOAD NEW REVISION button, you will see a file selector where you can
upload a file from your local machine.

After you have added several revisions, you can select which submitted revision is live with the drop-down.
GitHub integration
You may also use GitHub to manage your CloudScript (Legacy) revisions. You must have a GitHub account, and
you must be logged in.
Select the USE GITHUB button (the gray button in the previous screenshot).
The next window will have an orange AUTHORIZE GITHUB ACCOUNT button.
Create a new, empty repository in GitHub .
Return to the GitHub page in the PlayFab Game Manager (refresh tab).
At this point, you should be able to select your GitHub repository, and bind it to your title.

Once bound to GitHub, the manual upload option is removed, and new CloudScript (Legacy) revisions are
automatically made for each GitHub commit to the "master" branch.
If you commit multiple files, they will be concatenated together into a single PlayFab CloudScript (Legacy)
revision. Live revision selection remains the same: new commits to GitHub must be set to live in Game Manager
as described above.

Conclusion
CloudScript (Legacy) allows you to upload files to PlayFab, and execute your code on our server. You can
manage your CloudScript (Legacy) files from the Automation option in the left side bar. You can upload files
manually from your own computer, or bind your title to a GitHub account.
This quickstart covers managing your code files and uploading them to PlayFab.
If you have more questions, the Writing custom CloudScript (Legacy) tutorial explains more about how to write
your CloudScript (Legacy) code files.
CloudScript Tutorials
5/24/2022 • 2 minutes to read • Edit Online

These tutorials show you how to write, use, and handle error information with CloudScript.
ES6 features in CloudScript (Legacy)
Handling errors in CloudScript (Legacy)
Making Webhook calls from CloudScript (Legacy)
SDK error handling best practices
Writing custom CloudScript (Legacy)
ES6 features in CloudScript (Legacy)
5/24/2022 • 3 minutes to read • Edit Online

The CloudScript (Legacy) runtime environment supports most of the modern ECMAScript 6 features. While a
majority of these features are syntactical tricks, you can use them to improve and clean your CloudScript
(Legacy) code.
A complete overview of ES6 features is available in this Cheat Sheet.
This tutorial shows several tricks you may use in your CloudScript.

NOTE
Some of the features require strict mode. Enable this mode by placing the following code as the very first line of your
CloudScript file: use strict;

String interpolation
When composing messages for your players, you may want to use multi-line interpolated strings. Use the back-
tick symbol to create an interpolated string. You may then insert data right into the string using ${ variable }
syntax.
This allows you to avoid string concatenation and improves code readability.

NOTE
Back-tick strings are verbatim and may be multi-line. This means you have to keep an eye on all indention, as any extra
space/tab will be captured into the string.

function sendPushNotification(playerName, prizeAmount, newLevel) {


let message = `Congratulations ${playerName}!
You have reached level ${newLevel}.
You get ${prizeAmount} coins for your efforts.`;
// Use message variable and send push notification
// ...
}

New methods and arrow functions


ES6 brings new syntax for defining functions using the arrow operator => . The snippet displayed below shows
approximate translations for certain operator usages.
// The following snippets:
const add = (a,b) => a+b;

const add = (a,b) => {


return a+b;
}

// Both translate into something like


function add(a, b) {
return a+b;
}

This operator, combined with the new Array.findIndex method, allows searching by predicate with the
following well-looking, succinct code.

const players = [...]; // Suppose this is an array of Player Profiles

// Search by predicate: find item in 'players' that has 'DisplayName' set to 'Bob':
const bobIndex = players.findIndex(p => p.DisplayName === 'Bob');

Object assignment
The Object.assign method allows you to easily extend any object with a new set of properties and methods.
Having a large variety of usages, this method is particularly useful for extending a handlers object and creating
groups of handlers.

let TestHandlers = {
TestLeaderboards : (args, ctx) => {
// Test leaderboards code
},
TestPrizes : (args, ctx) => {
// Test prizes code
}
// ...
}

let ProductionHandlers = {
CleanUp : (args, ctx) => {
// System clean up code
},
GrantTournamentAccess : (args, ctx) => {
// Another useful production code
}
// ...
}

// Install both handler groups:


Object.assign(handlers, TestHandlers);
Object.assign(handlers, ProductionHandlers);

// Comment out the group to disable it but keep the relevant code
// Object.assign(handlers, SomeOtherHandlers);

This not only allows you to quickly enable and disable handler groups, but it also gives you a point to process
your handlers and wrap them with useful code, such as exception handling.
The following code extends the previous snippet with automatic exception logging. As an example, we log the
problem (which is not always useful), but you can extend the behavior to your taste.
// Handlers installer wraps the handler to catch error
function installHandlers(handlersObject) {
for (let property in handlersObject) {
handlersObject[property] = wrapHandler(handlersObject,property)
}
Object.assign(handlers, handlersObject);
}

// Utility
function wrapHandler(obj, key) {
if (obj.hasOwnProperty(key) && typeof obj[key] === 'function') {
let original = obj[key]; // Take the original function
return function() { // return a new function that
try { // Wraps the original invocation with try
return original.apply(null,arguments); // Do not forget to pass arguments
} catch (error) { // If error occurs
log.error(error); // We log it, but you may want to retry / do something else
throw error; // Rethrow to keep the original behaviour
}
}
} else { // If property is not a function, ignore it
return obj[key];
}
}

// Install handler groups:


installHandlers(TestHandlers);
installHandlers(ProductionHandlers);

Getters
One may use "Getters" to encapsulate common API calls into a more syntactically pleasing look and feel.
Consider the following Title Data state.

The following snippet shows how to retrieve Foo and Bar data from TitleData and then use them in a very
straightforward way.
'use strict'

// Define
let App = {
get TitleData() {
// Please, consider limiting the query by defining certain keys that you need
return server.GetTitleData({}).Data;
},
}

// Use
handlers.TestFooBar = () => {
// Client code is clean and does not show the fact of calling any functions / making api request
var titleData = App.TitleData; // Note that this implementation makes an API call every time it's
accessed
log.debug(titleData.Foo);
log.debug(titleData.Bar);
}
Handling errors in CloudScript (Legacy)
5/24/2022 • 2 minutes to read • Edit Online

This tutorial describes how to recognize and handle errors within your CloudScript (Legacy) handlers.

Identifying
The first step is identifying the error. While every uncaught error is logged and available from the response to
the caller (client), you can catch the error early by using a try/catch block.
Consider the following CloudScript (Legacy) snippet that produces and catches the error.

"use strict";

handlers.GenerateError = () => {
try {
server.GetPlayerStatistics({
PlayFabId : "non-existing-player-id"
});
} catch (ex) {
let error = ex.apiErrorInfo.apiError.error; // In this case - "InvalidParams"
let errorCode = ex.apiErrorInfo.apiError.errorCode; // In this case : 1000
}
}

Notice how the error codes were extracted within the catch block? Consult our Global API method error codes
documentation for a complete list of errors.

NOTE
The error code on its own is sufficient to identify the error.

Logging
Any unhandled error is added to the response, allowing the client to process the problem.
At the same time, it creates a CloudScript (Legacy) error entry and adds it to the total statistics available on your
CloudScript (Legacy) dashboard.

To force-log the exception in the form of a JSON string, use error logging via the log object.
"use strict";

handlers.GenerateError = () => {
try {
server.GetPlayerStatistics({
PlayFabId : "non-existing-player-id"
});
} catch (ex) {
log.error(ex);
}
}

Finally, you can write title/player events for later processing through analytics.

"use strict";

handlers.GenerateError = () => {
try {
server.GetPlayerStatistics({
PlayFabId : "non-existing-player-id"
});
} catch (ex) {
server.WriteTitleEvent({
EventName : 'cs_error',
Body : ex
});
}
}

Recovery
It's not always possible to recover from errors. Issues such as InvalidArguments leave you with no option but to
report the problem back to the player.
There are a subset of errors where a retry strategy can be applied. Retry-able error types are described in the
Global API Method Error Codes.
We ask that you make sure you meet the following requirements when applying a retry strategy:
With each retry, the delay between retries should increase exponentially. This increases your chances for a
successful call, and prevents your game from spamming the PlayFab server (which will result in more
rejected calls).
You should apply this retry strategy selectively, only using it for those codes that are worth retrying.

CloudScript timeout error


The execution time of CloudScript (Legacy) API calls is limited to 4 seconds.
If the execution time exceeds 4 seconds, an InternalServerError is raised and the PlayStream Event writes a
Logs object similar to the following:
"Logs":[
{
"Level":"Error",
"Message":"PlayFab API request failure",
"Data":{
"request":{
"PlayFabId":"9437A5ADDAE3012D"
},
"error":"Timeout",
"api":"/Server/GetPlayerSegments"
}
}
]

If you encounter this error, you can:


break your CloudScript (Legacy) into smaller code segments which will run in under 4 seconds.
Switch to CloudScript using Azure Functions, which has longer timeout limits in some cases. You can view the
limits in the quickstart guide.
Making Webhook calls from CloudScript (Legacy)
5/24/2022 • 3 minutes to read • Edit Online

One of the less well-known features of CloudScript (Legacy) is that you can make Webhook calls from it to any
web API endpoint, using standard Representational State Transfer (REST) calls.

NOTE
We recommend you make webhook calls using the newer CloudScript Functions when possible.

This allows titles to make calls to basic informational services, but it also enables more complex scenarios (such
as using OAuth), to secure a communication to an endpoint you own.
This tutorial discusses making Webhook calls from CloudScript (Legacy), for both non-secure and secure
scenarios.
As a REST call, the structure of a Webhook call from CloudScript (Legacy) is simple. The elements to be specified
are:
The URL endpoint.
The REST method (post, get, put, or delete).
Any headers required.
The content type (most commonly application/JSON).
The content itself (body).
For example, a basic web API call to get the version number of your server-side logic might look something like
the example provided below.

// CloudScript (Legacy)
var url = "http://api.yoursite.com/playfab_call/GetVersion";
var method = "post";
var contentBody = "";
var contentType = "application/json";
var headers = {};
var responseString = http.request(url,method,contentBody,contentType,headers);

The body of the response is returned in stringified form, so that you can subsequently use it in the rest of the
script.
In this case, since we were querying version, you might write the response out to the log like the one provided
here.

// CloudScript (Legacy)
log.info(responseString);

The response back to the client at the end of running the CloudScript might look like this example provided
below.
//HTTP Response
{
"code": 200,
"status": "OK",
"data":
{
"FunctionName": "MyScript",
"Revision": 23,
"FunctionResult": true,
"Logs": [
{
"Level": "Info",
"Message": "{\"version\": 3}"
}],
"ExecutionTimeSeconds": 0.4309841,
"MemoryConsumedBytes": 29608,
"APIRequestsIssued": 0,
"HttpRequestsIssued": 1
}
}

If, however, you have a secure service you need to communicate with, you will first need to exchange credentials
with that service to establish identity.
For an OAuth solution, that means requesting a Bearer Access token, using your client ID and secret. This will
vary based upon your specific OAuth implementation, but your call could look something like the following
example.

//CloudScript (Legacy)
var url = "https://api.yoursite.com/playfab_call/request_token";
var method = "post";
var contentBody = "grant_type=client_credentials";
var contentType = "application/x-www-form-urlencoded";
var headers = {};
headers["client_id"] = clientId;
headers["client_secret"] = clientSecret;

var tokenResponse = http.request(url,method,contentBody,contentType,headers);

Given a good response, you would then be able to parse the bearer_access_token from the response like this
(again, this does depend upon the specifics of your OAuth implementation, but this is a fairly common pattern
for this form of authentication).

//CloudScript (Legacy)
var parsedData = JSON.parse(tokenResponse);
var bearer_access_token = parsedData["access_token"];

This would then allow you to call into your OAuth-secured functionality by providing the bearer_access_token .

//CloudScript (Legacy)
var url = "https://api.yoursite.com/playfab_call/do_action";
var method = "post";
var contentBody = customActionBody;
var contentType = "application/json";
var headers = {};
headers["authorization"] = "Bearer " + bearer_access_token;

So the basic pattern in this case is that you use your application’s client ID and secret, in order to obtain the
unique Bearer Access token for the call - and then use it to secure that call.
As you can see, these calls would all be made using SSL, in order to help prevent man-in-the-middle attacks.
Using HTTP calls from CloudScript (Legacy), you can make calls into any other web API you need to for your
title. This allows you to extend your title functionality beyond even what PlayFab offers directly, giving you the
option to make and use your own custom services - or access others.
Because this all takes place within CloudScript (Legacy), it provides a server-authoritative context in which to
make those calls. This means that they will have the necessary protections in your CloudScript (Legacy) to help
prevent players from cheating, or accessing features and data they shouldn’t.
SDK error handling best practices
5/24/2022 • 2 minutes to read • Edit Online

This tutorial shows how to access, recognize, and handle API errors using the PlayFab SDK.
The practices described here are equally applicable to the admin, server, and client SDKs - but the patterns
depend highly on the language of your choice.
Simply put, the pattern of your choice will be valid for any SDK (admin/server/client) but implementation details
will be specific to your programming language and environment.

Catching and accessing the error


PlayFab SDKs usually report errors by returning an error object. The following snippet shows how to detect and
access the error.

PlayFabClientAPI.LoginWithEmailAddress(new LoginWithEmailAddressRequest() {
Email = "doesnotexist@mail.com",
Password = "nevercorrect",
}, result => {
// success
}, error => {
// 'error' object is our point of access to error data
});

Generally, if an error object is defined (not null), it indicates that an error has occurred. We may then further
inspect the error.

Inspecting the error


The most common way to inspect an error is to recognize it through the code. As described in the Global API
Method Error Codes, each generated error contains human-readable and numeric error codes.

NOTE
The code on its own is sufficient to recognize and process the error accordingly.

Let's take the LoginWithEmailAddress API method as an example. As stated in the documentation for this
method, the following internal errors may be thrown upon execution:
InvalidTitleId 1004
AccountNotFound 1001
InvalidEmailOrPassword 1142
RequestViewConstraintParamsNotAllowed 1303

The following method illustrates how to inspect and recognize such an error.
PlayFabClientAPI.LoginWithEmailAddress(new LoginWithEmailAddressRequest() {
Email = "doesnotexist@mail.com",
Password = "nevercorrect",
}, result => {
// success
}, error => {
// General purpose logging: GenerateErrorReport gives a bunch of information about the error
Debug.Log(error.GenerateErrorReport());

// Recognize and handle the error


switch (error.Error) {
case PlayFabErrorCode.InvalidTitleId:
// Handle invalid title id error
break;
case PlayFabErrorCode.AccountNotFound:
// Handle account not found error
break;
case PlayFabErrorCode.InvalidEmailOrPassword:
// Handle invalid email or password error
break;
case PlayFabErrorCode.RequestViewConstraintParamsNotAllowed:
// Handle not allowed view params error
break;
default:
// Handle unexpected error
break;
}
});

Handling the error


Once the error is identified, the handle/recover strategy depends on the error type and nature. Errors such as
invalid arguments will never succeed if retried. The request must be fixed for that API call to succeed.
There is a sub-set of errors, where a retry strategy can be applied. Retry-able error types are described in the
Global API Method Error Codes.
Please make sure to meet the following requirements when applying a retry strategy:
With each retry, the delay between retries should increase exponentially. This increases your chances for a
successful call, and prevents your game from spamming the PlayFab server (which will result in more
rejected calls).
You should apply this retry strategy selectively, only using it for those codes that are worth retrying.
See our Global API Method Error Codes tutorial for a list of codes that are safe to retry.
Writing custom CloudScript
5/24/2022 • 13 minutes to read • Edit Online

CloudScript is one of PlayFab's most versatile features. It allows client code to request execution of any kind of
custom server-side functionality you can implement, and it can be used in conjunction with virtually anything.

NOTE
CloudScript using Azure Functions improves on what made CloudScript (Legacy) great with more supported languages
and better debugging workflows.

This tutorial covers writing your CloudScript (Legacy) code. Please see the CloudScript (Legacy) quickstart for
help in uploading your CloudScript (Legacy) files to your title.

NOTE
This tutorial demonstrates Unity code samples, but CloudScript (Legacy) works similarly for all SDKs.

Prerequisites for this tutorial:


Unity environment set up with the PlayFab Unity SDK
The title ID is set in the PlayFabSharedSettings object.
The project can successfully log in a user.

Getting started: helloWorld


Our helloWorld example works on a brand new title, with no modifications in Game Manager. The default
CloudScript (Legacy) file for a new title includes a handler called helloWorld . It utilizes a few basic features,
input parameters, logging, currentPlayerId, and return parameters.
The following sample shows the default helloWorld function code (minus comments).

// CloudScript (JavaScript)
handlers.helloWorld = function (args, context) {
var message = "Hello " + currentPlayerId + "!";
log.info(message);
var inputValue = null;
if (args && args.hasOwnProperty("inputValue"))
inputValue = args.inputValue;
log.debug("helloWorld:", { input: inputValue });
return { messageValue: message };
}

Deconstruct the code


The handler object is pre-defined in the PlayFab CloudScript (Legacy) environment. You should add any of your
CloudScript (Legacy) functions to this object.
helloWorld is a function made available to your title and SDKs, because it is defined in the handler object.
argsis an arbitrary object which comes from the caller. It is parsed from JSON, and can contain any data
formatted in any way.
See FunctionParameter in the next section.

WARNING
You should treat this object with zero trust. A hacked client or malicious user can provide any information here in any
format.

Context is an advanced parameter. In this example, it is null. This parameter is server-controlled and safe.
currentPlayerId is a global variable, which is set to the PlayFabId of the player requesting this call. This
parameter is server-controlled and safe. Note: When using ExecuteEntityCloudScript API this parameter
is null unless the entity has a MasterPlayerID in its entity chain.
log.info : log is a global object. It is primarily used for debugging your CloudScript (Legacy). The log
object exposes the following methods: info , debug , and error . There are more details later in this
tutorial.
return : any object you return is serialized as JSON, and returned to the caller. You may return any JSON
serialize-able object with any data you wish.

WARNING
It is your responsibility if your CloudScript (Legacy) returns secret data to your clients. A hacked client or malicious user
can examine the returned data, even if you don't display it to the user in regular game play.

Executing CloudScript (Legacy) functions from a Unity game client


Calling a CloudScript (Legacy) function from within a client is straightforward. You first have to create an
ExecuteCloudScriptRequest , and set the ActionId property to the name of the CloudScript (Legacy) function
you wish to execute (in this case it would be helloWorld ), then send the object to PlayFab via our API.

NOTE
You can only call CloudScript (Legacy) methods attached to the handlers JavaScript object.

To execute CloudScript (Legacy) methods, you will need the following lines of code in your client.

// Build the request object and access the API


private static void StartCloudHelloWorld()
{
PlayFabClientAPI.ExecuteCloudScript(new ExecuteCloudScriptRequest()
{
FunctionName = "helloWorld", // Arbitrary function name (must exist in your uploaded cloud.js file)
FunctionParameter = new { inputValue = "YOUR NAME" }, // The parameter provided to your function
GeneratePlayStreamEvent = true, // Optional - Shows this event in PlayStream
}, OnCloudHelloWorld, OnErrorShared);
}
// OnCloudHelloWorld defined in the next code block

Deconstruct the code


ExecuteCloudScriptRequest is the request type for any call to PlayFabClientAPI.ExecuteCloudScript.
ExecuteCloudScriptRequest.FunctionName is a string. The value should match the name of the function
defined in CloudScript (Legacy). In this case, helloWorld .
ExecuteCloudScriptRequest.FunctionParameter can be any object, able to be serialized to JSON. It becomes
the first args parameter in the helloWorld function (refer to the args in the previous section).
is optional. If true, an event will be posted to
ExecuteCloudScriptRequest.GeneratePlayStreamEvent
PlayStream, which you can view in Game Manager, or utilize for other PlayStream triggers.
Depending on the language, the final part of the ExecuteCloudScript line involves making the request to the
PlayFab CloudScript (Legacy) server, as well as the Result and Error handling part, specific for the language.
For example, in Unity, JavaScript, or AS3, Error and Result handling is provided using callback functions.
In pure C# , however, the SDK allows more succinct code by means of the async/await construct - as seen in the
following example.

private static void OnCloudHelloWorld(ExecuteCloudScriptResult result) {


// CloudScript (Legacy) returns arbitrary results, so you have to evaluate them one step and one
parameter at a time
Debug.Log(JsonWrapper.SerializeObject(result.FunctionResult));
JsonObject jsonResult = (JsonObject)result.FunctionResult;
object messageValue;
jsonResult.TryGetValue("messageValue", out messageValue); // note how "messageValue" directly
corresponds to the JSON values set in CloudScript (Legacy)
Debug.Log((string)messageValue);
}

private static void OnErrorShared(PlayFabError error)


{
Debug.Log(error.GenerateErrorReport());
}

Intermediate Overview: Globals and advanced arguments


CloudScript (Legacy) is a set of JavaScript functions compiled with V8 and hosted on PlayFab's servers. It has
access to any server API listed in the PlayFab API reference documentation, along with a logger, the PlayFab ID
of the player making the CloudScript (Legacy) request, and any information included with the request, all in the
form of preset objects.
CloudScript (Legacy) functions themselves are properties of a global handlers object. The following table shows
a complete list of these predefined variables.

NAME USE

ser ver Has access to all server-side API calls listed in the PlayFab
API reference documentation. They can be called
(synchronously) like so:
var result =
server.AuthenticateUserTicket(request);

http Performs synchronous HTTP requests, like so:


http.request(url, method, content, contentType,
headers, logRequestAndResponse)
. The headers object contains properties corresponding to
various headers and their values. logRequestAndResponse
is a boolean that determines whether the title should log
any errors in the request as part of the response.
NAME USE

log Creates log statements and adds them to the response.


Logs have three levels: log.info() , log.debug() , and
log.error() . All three levels take a message string, along
with an optional object containing extra data to include with
the log. For example,
log.info('hello!', { time: new Date() });

currentPlayerId PlayFab ID of the player who triggered the CloudScript


(Legacy) call.

handlers Global object that contains all CloudScript (Legacy) functions


for your title. Functions can be added or called through this
object. For example, handlers.pop = function() {}; ,
handlers.pop(); .

script Global object that contains Revision and titleId .


Revision represents the Revision Number for the
currently executing CloudScript (Legacy), and titleId
represents the ID for the current title.

In addition, all handler functions are passed two parameters, detailed below.

NAME USE

args First parameter to a handler function. An object


representation of the FunctionParameter field of an
ExecuteCloudscript request.

context Second parameter to a handler function. Additional


information about the request when it is triggered by a
PlayStream event action, including the data from the event
that triggered the action (context.playStreamEvent) and the
profile data for the player associated with it.
(context.playerProfile)

CloudScript (Legacy) functions can be called through the ExecuteCloudScript API, or by a preset PlayStream
event action.
Full details about the response to ExecuteCloudScript can be found in the ExecuteCloudScriptResult.

Intermediate: FunctionParameter and args


In the previous section, we described how to populate the request.FunctionParameter , and view that info in the
args parameter. The CloudScript quickstart demonstrates how to upload new CloudScript (Legacy).

Putting both together, we can provide another example of how to pass arguments from client to CloudScript
(Legacy). Take the previous example, and modify the CloudScript (Legacy) code and your client code as shown
below.
handlers.helloWorld = function (args) {
// ALWAYS validate args parameter passed in from clients (Better than we do here)
var message = "Hello " + args.name + "!"; // Utilize the name parameter sent from client
log.info(message);
return { messageValue: message };
}

// Build the request object and access the API


private static void StartCloudHelloWorld()
{
PlayFabClientAPI.ExecuteCloudScript(new ExecuteCloudScriptRequest()
{
FunctionName = "helloWorld", // Arbitrary function name (must exist in your uploaded cloud.js file)
FunctionParameter = new { name = "YOUR NAME" }, // The parameter provided to your function
GeneratePlayStreamEvent = true, // Optional - Shows this event in PlayStream
}, OnCloudHelloWorld, OnErrorShared);
}

private static void OnCloudHelloWorld(ExecuteCloudScriptResult result) {


// CloudScript (Legacy) returns arbitrary results, so you have to evaluate them one step and one
parameter at a time
Debug.Log(JsonWrapper.SerializeObject(result.FunctionResult));
JsonObject jsonResult = (JsonObject)result.FunctionResult;
object messageValue;
jsonResult.TryGetValue("messageValue", out messageValue); // note how "messageValue" directly
corresponds to the JSON values set in CloudScript (Legacy)
Debug.Log((string)messageValue);
}

private static void OnErrorShared(PlayFabError error)


{
Debug.Log(error.GenerateErrorReport());
}

After making these changes, you can now easily send and receive data between CloudScript (Legacy) and your
clients.

NOTE
It is important to point out that any data coming from your clients is susceptible to hacking and exploitation.

You will always want to validate input parameters prior to updating your back end. The process for validating
input parameters will vary from title to title, but the most basic validation will check to ensure inputs are within
acceptable ranges and periods.

Intermediate: Calling the server APIs


As mentioned before, within CloudScript (Legacy) methods, you have access to the full set of Server API calls.
This enables your cloud code to act as a dedicated server.
Common server tasks:
Update player statistics and data.
Grant items and currency.
Randomly generate game data.
Securely calculate battle results and more...
See the Server APIs listed in our PlayFab API Reference documentation for required parameters and object
structures.
The following example is from within a potential CloudScript (Legacy) handler.

// CloudScript (Legacy) (JavaScript)


//See: JSON.parse, JSON.stringify, parseInt and other built-in javascript helper functions for manipulating
data
var currentState; // here we are calculating the current player's game state

// here we are fetching the "SaveState" key from PlayFab,


var playerData = server.GetUserReadOnlyData({"PlayFabId" : currentPlayerId, "Keys" : ["SaveState"]});
var previousState = {}; //if we return a matching key-value pair, then we can proceed otherwise we will need
to create a new record.

if(playerData.Data.hasOwnProperty("SaveState"))
{
previousState = playerData.Data["SaveState"];
}

var writeToServer = {};


writeToServer["SaveState"] = previousState + currentState; // pseudo Code showing that the previous state is
updated to the current state

var result = server.UpdateUserReadOnlyData({"PlayFabId" : currentPlayerId, "Data" : writeToServer,


"Permission":"Public" });

if(result)
{
log.info(result);
}
else
{
log.error(result);
}

Advanced: PlayStream event action


The other way to call a CloudScript (Legacy) function is as a PlayStream event action.
1. In any browser:
Visit the PlayFab Game Manager .
Find your Title .
Go to the PlayStream tab.
Go to the Event Actions tab.
The page will look like the example provided below.
2. Use the New Action button to create a new action.
Give the new Action a name.
To make the Action trigger a CloudScript (Legacy) function, add an Action with the button in that
section.
Then select the option in the Type drop-down menu.
Select the helloWorld function in the CloudScript function drop-down menu.
Select the Save Action button.

3. Right now, this Action is set to trigger on any PlayStream event. To test it:
Check the Publish results as PlayStream Event box.
Save the Action .
Then trigger an event.
In the PlayStream Debugger , a new event that corresponds to the CloudScript (Legacy) execution
should be present which contains the appropriate information.
For more information on checking a PlayStream event in the debugger, see the following section
Advanced: Debugging CloudScript (Legacy).

NOTE
Event actions can only use the live revision when calling CloudScript (Legacy) functions. If you cannot find the
helloWorld function in the drop-down, this is the most likely reason.

Advanced: Debugging CloudScript (Legacy)


NOTE
Debugging is much easier with CloudScript using Azure Functions. We recommend migrating for access to great features
like local debugging for CloudScript

Logging
One of the most important tools for debugging code is logging. Our CloudScript (Legacy) provides a utility for
performing the function.
This takes the form of the log object, which can log any message desired using the Info , Debug , and Error
methods.
Additionally, the HTTP object will log any errors it comes across while making requests by setting the
logRequestAndResponse parameter. While setting these logs up is simple, accessing them takes a bit of finesse.

Here is an example of a CloudScript (Legacy) function that uses all 4 types of logs.

handlers.logTest = function(args, context) {


log.info("This is a log statement!");
log.debug("This is a debug statement.");
log.error("This is... an error statement?");
// the last parameter indicates we want logging on errors
http.request('https://httpbin.org/status/404', 'post', '', 'text/plain', null, true);
};

To run this example, add this function to your live revision before proceeding.
The logTest function can be called using ExecuteCloudScript as shown below.

// Invoke this on start of your application


void Login() {
PlayFabClientAPI.LoginWithCustomID(new LoginWithCustomIDRequest {
CreateAccount = true,
CustomId = "Starter"
}, result => RunLogTest(), null);
}

void RunLogTest() {
PlayFabClientAPI.ExecuteCloudScript(new ExecuteCloudScriptRequest {
FunctionName = "logTest",
// duplicates the response of the request to PlayStream
GeneratePlayStreamEvent = true
}, null, null);
}
// Logs evaluated in next code block
Setting GeneratePlayStreamEvent makes the CloudScript (Legacy) function call generate a PlayStream event,
which includes the contents of the response. To find the contents of a PlayStream event:
Go to either the Game Manager home page for your Title or its PlayStream tab.
The PlayStream Debugger will display events as they come in.
When they arrive, select the small blue Info icon in the top right corner of the event, as shown below.

Selecting this will display the raw JSON of the event, which is detailed for each event here. An example of this
JSON can be seen in the following example.
If we add the LogScript MonoBehavior to the scene, running the game will yield this in PlayStream.
The result of an ExecuteCloudScript call includes a field called Logs , which is a list of log objects generated by
the CloudScript (Legacy) function.
You can see the three log calls, as well as the log from the invalid HTTP request. The HTTP request log also
makes use of the Data field, unlike the log calls.
This field is a JavaScript object that can be populated by any information relevant to the log statement. Calls to
log can make use of this field as well, using the second parameter, as indicated below.

handlers.logTest = function(args, context) {


log.info("This is a log statement!", { what: "Here on business." });
log.debug("This is a debug statement.", { who: "I am a doctor, sir" });
log.error("This is... an error statement?", { why: "I'm here to fix the plumbing. Probably.", errCode:
123 });
};

These calls will all populate the Data field in the result with their second parameter.
Since the logs are included in the result, the client-side code can respond to log statements. The error in the
logTest function is forced, but the client code can be adapted to respond to it.

void RunLogTest()
{
PlayFabClientAPI.ExecuteCloudScript(
new ExecuteCloudScriptRequest
{
FunctionName = "logTest",
// handy for logs because the response will be duplicated on PlayStream
GeneratePlayStreamEvent = true
},
result =>
{
var error123Present = false;
foreach (var log in result.Logs)
{
if (log.Level != "Error") continue;
var errData = (JsonObject) log.Data;
object errCode;
var errCodePresent = errData.TryGetValue("errCode", out errCode);
if (errCodePresent && (ulong) errCode == 123) error123Present = true;
}

if (error123Present)
Debug.Log("There was a bad, bad error!");
else
Debug.Log("Nice weather we're having.");
}, null);
}

If this code is run, the output should indicate the presence of the error. Realistic error responses might be to
display the error in the UI, or save a value in a log file.

Advanced: Errors
In development, CloudScript (Legacy) errors will often not be manually triggered - as in the case of log.error .
Fortunately, the response to ExecuteCloudScript contains an ExecuteCloudScriptResult which includes a
ScriptExecutionError field. Adapting the last example from the logging section, we might use it as shown below.

void RunLogTest() {
PlayFabClientAPI.ExecuteCloudScript(new ExecuteCloudScriptRequest {
FunctionName = "logTest",
// handy for logs because the response will be duplicated on PlayStream
GeneratePlayStreamEvent = true
}, result => {
if(result.Error != null) {
Debug.Log(string.Format("There was error in the CloudScript function {0}:\n Error Code: {1}\n
Message: {2}"
, result.FunctionName, result.Error.Error, result.Error.Message));
}
},
null);
}

In the event that some error occurred, this code would display it in the log.
PlayFab CloudScript using Azure Functions
5/24/2022 • 2 minutes to read • Edit Online

PlayFab CloudScript using Azure Functions is a new feature that enables serverless compute on demand in the
language of your choice. In order to do this we leverage Azure Functions and provide you with a tight
integration via Visual Studio Code.
Using Azure Functions to run cloud code that is bound to a PlayFab title gives you the power of C# and strongly
typed code. It also gives you the ability to leverage any number of Azure features such as CosmosDB.
Basing CloudScript on Azure Functions brings a few key improvements:
1. Ability to write Cloudscript in C# as well as Javascript and the other supported Azure Functions languages
2. Ability to locally debug Cloudscript using Visual Studio or Visual Studio Code. In addition, we have released
an open sourced Visual Studio Code Extension for PlayFab that makes it easier to create CloudScript using
Azure Functions.
3. Ability to write queued Cloudscript functions that can run for extended periods of time since we
asynchronously wait for it to complete.
4. No limits to the number of API calls within the Azure Function code.

NOTE: For more information about Azure Functions please visit the Azure Functions documentation

Types of Cloud Script using Azure Functions


One of the major new capabilities of CloudScript is the ability to have long running CloudScript. This is
introduced by having a new type of Cloud Script based on Azure Functions queued storage triggered Cloud
Script. With this new type of CloudScript, you will need to decide the type of CloudScript to use for each
CloudScript you create.
For more information about the advantages and limitations of each type of function you can read the Azure
documentation of each:
HTTP Triggered Cloud Script
Queued Triggered Cloud Script
Pricing
To use this feature, you must bring your own Azure subscription. This means that usage charges will apply to
your Azure subscription the same as if you used Azure Functions without a PlayFab integration. For more
information about pricing, see Azure Function pricing on the Azure site.
Getting Started
To get started with CloudScript using Azure Functions read our quickstart guide and watch our getting started
video.
Quickstart: Writing a PlayFab CloudScript using
Azure Functions
5/24/2022 • 6 minutes to read • Edit Online

In this quickstart, you write a CloudScript using Azure Functions with Visual Studio Code, Azure Functions C#
and Unity C#. After finishing this guide you will be able to link your new CloudScript to rules, scheduled tasks or
even call it from your client code.

Prerequisites
There are a couple of steps needed to get started with PlayFab C# CloudScript.
Visit the Visual Studio Code QuickStart: Create an Azure Functions project using Visual Studio Code and
return here once you are completely set up. The following prerequisites are covered in their quickstart guide:
An Azure account. Signing up for an Azure Account is free
An Azure Subscription
A Functions App resource configured in the Azure Portal
To minimize latency of your CloudScript using Azure Functions place them in the US-West, US-
West 2, or US-West 3 Azure regions.
Security Note: From a security perspective you should make sure to only use a given function
secret with PlayFab and not use it for calling the same function from any other source.
Security Note: For queued functions you should set up a distinct storage account for the
queues used for the queue trigger.
A PlayFab account

NOTE
PlayFab Azure Functions can use the Azure Functions V2 runtime or greater, and .NET Core 2 or greater. We recommend
that you use the latest version (currently Azure Functions V3 and .NET Core 3).

Create an Azure Function


1. Create a basic "HelloWorld" example function. You can see how to do this by following the Create your
first function using Visual Studio Code guide. For a code example using PlayFab variables, see the section
below PlayFab Function Context, Variables and using the Server SDKs.

IMPORTANT
The "Create your first function using Visual Studio Code" guide instructs you to set the Authorization Level of your
Azure Function to Anonymous . This is done to simplify testing.
In a production environment, in most cases, you shouldn't use Anonymous authorization since it enables anyone
to call your function endpoint. To properly secure your function in the PlayFab environment, we recommend that
you use Function level authorization.

2. After you create and deploy your function, select the Register Function button in the top right hand
corner of the Functions (Preview) page.
NOTE
If your Azure Function uses Function level authorization, you must register the URL that passes the
Authorization key. For information on retrieving the URL with Authorization keys, see "Run the function in Azure"
in Quickstart: Create a function in Azure using Visual Studio Code.

3. For Name , enter a human-friendly name for your function. For Function URL , enter the HTTP Trigger
URL of the function. The URL can be found in the output of your deployment.

For more information about deploying Azure functions, see Deploy Azure Functions from Visual Studio Code.

Using and Calling CloudScript using Azure Functions from your


PlayFab Title
The example code in this guide is written in Unity C# & Azure Function C# code.
Now that your function is registered, you can call that function from within your client.
//This snippet assumes that your game client is already logged into PlayFab.

using PlayFab;
using PlayFab.CloudScriptModels;

private void CallCSharpExecuteFunction()


{
PlayFabCloudScriptAPI.ExecuteFunction(new ExecuteFunctionRequest()
{
Entity = new PlayFab.CloudScriptModels.EntityKey()
{
Id = PlayFabSettings.staticPlayer.EntityId, //Get this from when you logged in,
Type = PlayFabSettings.staticPlayer.EntityType, //Get this from when you logged in
},
FunctionName = "HelloWorld", //This should be the name of your Azure Function that you created.
FunctionParameter = new Dictionary<string, object>() { { "inputValue", "Test" } }, //This is the
data that you would want to pass into your function.
GeneratePlayStreamEvent = false //Set this to true if you would like this call to show up in
PlayStream
}, (ExecuteFunctionResult result) =>
{
if (result.FunctionResultTooLarge ?? false)
{
Debug.Log("This can happen if you exceed the limit that can be returned from an Azure Function,
See PlayFab Limits Page for details.");
return;
}
Debug.Log($"The {result.FunctionName} function took {result.ExecutionTimeMilliseconds} to
complete");
Debug.Log($"Result: {result.FunctionResult.ToString()}");
}, (PlayFabError error) =>
{
Debug.Log($"Opps Something went wrong: {error.GenerateErrorReport()}");
});
}

PlayFab CloudScript Context, Variables and Server SDKs


One advantage of using CloudScript using Azure Functions is that the PlayStream Event and Player Profile
context is automatically passed to the Azure Function. On invocation of the Cloudscript you receive the context
and in what context the Function was called. For example, whether it was triggered by a PlayStream Action or
called directly from the client. This includes information such as the entity profile on whose behalf the
CloudScripts was invoked, and potentially the PlayStream events used to invoke the CloudScript.
There are a couple of steps that you need to do if you are coding Functions without our PlayFab Visual Studio
Code Extension.
1. You will need to install the PlayFab SDK via Package Manager. To do this open Terminal or CMD Console in
Visual Studio Code and type: dotnet add package PlayFabAllSDK
2. We have created some helpers that will ship with the cSharpSDK.
3. You need to edit your .csproj file and include <DefineConstants>NETCOREAPP2_0</DefineConstants> in your
default PropertyGroup or NETCOREAPP3_1 if you are using the latest.
4. Execution of a script can occur through several methods (APIs, Scheduled Tasks, PlayStream Event,
Segment Entering and Exit method). The context of the execution is important to implement your
CloudScript. See the Using CloudScript context models tutorial for details on how to use the context of
the script.
A Hello World example is always nice, see the HelloWorld Sample below that you can use as your first Azure
Function. To compile and run the sample, you need to include the CS2AFHelperClasses.cs file which contains the
implementation of PlayFab.Samples namespace.

using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using PlayFab.Samples;

namespace PlayFabCS2AFSample.HelloWorld
{
public static class HelloWorld
{
[FunctionName("HelloWorld")]
public static async Task<dynamic> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
FunctionExecutionContext<dynamic> context =
JsonConvert.DeserializeObject<FunctionExecutionContext<dynamic>>(await req.ReadAsStringAsync());

dynamic args = context.FunctionArgument;

var message = $"Hello {context.CallerEntityProfile.Lineage.MasterPlayerAccountId}!";


log.LogInformation(message);

dynamic inputValue = null;


if (args != null && args["inputValue"] != null)
{
inputValue = args["inputValue"];
}

log.LogDebug($"HelloWorld: {new { input = inputValue} }");

return new { messageValue = message };


}
}
}

In the example, the CurrentPlayerId of the caller is available as it is in our traditional CloudScript
implementation. Parameters that you pass in the FunctionParameters field are available in the args. But, unlike
the Hello World example in Create your first function using Visual Studio Code guide, parameters are passed in
the POST body instead of the query string.
To call the HelloWorld Azure Function from a PlayFab SDK use ExecuteFunction .

Azure Function Rules


Azure Functions can also be called by creating rules and scheduled tasks. This works in the same way as our
standard CloudScript. To create a rule or scheduled task, go to Automation > Rules or Automation >
Scheduled Tasks .
Click New Rule
Enter a name for your rule
Select the event type that this rule will trigger on
Add an action
From the action dropdown select Execute Azure Function
A list of available Azure Functions that you've registered will be available in the drop-down list.

Debugging your Azure Function


With Azure functions, you now have the option to debug your CloudScript locally or in the Azure portal. To learn
more about portal debugging, see Debugging CloudScript using Azure Functions with the Azure portal. To learn
how to set up local debugging, see Local debugging for Cloudscript using Azure Functions.

Execution limits
CloudScript calls to Azure Functions have timeout limits. If your webhook takes too long to execute, the request
will time out in PlayFab. Make sure your code can execute fast enough to stay under the timeout limits.

SO URC E A C T IO N T Y P E L IM IT ( SEC O N DS)

PlayFab API HTTP request 10

PlayStream V2 HTTP request 10


SO URC E A C T IO N T Y P E L IM IT ( SEC O N DS)

Scheduled task HTTP request 4.5

PlayStream V1 HTTP request 1

Queue function Queue payload 1


Tutorial: Using CloudScript context models
5/24/2022 • 4 minutes to read • Edit Online

PlayFab executes scripts through several mechanisms including execution through APIs, through scheduled
tasks, through PlayStream events, and when a player enters and exits segments. In many cases, the context in
which the script executes is important to how it runs. An example of this is knowing the Player ID of the player
on whose behalf the script is being run. The context in which your script is run determines the available data
model and provides context specific data that is used in your script.
In this tutorial, you learn how to:
Use the shared context model
Use the context model when executing via the ExecuteFunction API.
Use the context model when executing via Scheduled Task.
Use the context model when executing in the context of a Player.
Use the context model when executing in the context of an Entity.

Use the shared Title Authentication context model


No matter the method for executing a script the Title Authentication context is always provided. This includes the
Title ID and Entity Token (see GetEntityToken for more details) used to execute the script. Knowing this context
allows you to make additional API calls in your script into PlayFab using the Server APIs.

// Shared models
public class TitleAuthenticationContext
{
public string Id { get; set; }
public string EntityToken { get; set; }
}

Use the context model when executing via the ExecuteFunction API
When you use the the ExecuteFunction API to execute a script, the context that is provided includes the following
information:
The Entity Profile of the caller
The Title Authentication Context
A boolean that indicates whether a PlayStream event is sent as part of the function being executed
The functions arguments used when calling the script
// Models via ExecuteFunction API
public class FunctionExecutionContext<T>
{
public PlayFab.ProfilesModels.EntityProfileBody CallerEntityProfile { get; set; }
public TitleAuthenticationContext TitleAuthenticationContext { get; set; }
public bool? GeneratePlayStreamEvent { get; set; }
public T FunctionArgument { get; set; }
}

public class FunctionExecutionContext : FunctionExecutionContext<object>


{
}

Use the context model when executing via Scheduled Task


When you Scheduled Tasks to execute a script, the context that is provided includes the following information:
The Scheduled Task Name Id
The event history which includes a stack of PlayStream Events
The title Authentication Context
A boolean that indicates whether a PlayStream event is sent as part of the function being executed
The functions argument used when calling the script

// Models via Scheduled task


public class PlayStreamEventHistory
{
public string ParentTriggerId { get; set; }
public string ParentEventId { get; set; }
public bool TriggeredEvents { get; set; }
}

public class ScheduledTaskFunctionExecutionContext<T>


{
public PlayFab.CloudScriptModels.NameIdentifier ScheduledTaskNameId { get; set; }
public Stack<PlayStreamEventHistory> EventHistory { get; set; }
public TitleAuthenticationContext TitleAuthenticationContext { get; set; }
public bool? GeneratePlayStreamEvent { get; set; }
public T FunctionArgument { get; set; }
}

public class ScheduledTaskFunctionExecutionContext : ScheduledTaskFunctionExecutionContext<object>


{
}

Use the context model when executing in the context of a Player


When executing a script through Player PlayStream Events, entering or leaving an segment or as part of a
segment based scheduled task the context that is provided includes the following information:
The Player Profile
Boolean indicating if the player profile is trunctated.
The Player Profile will be truncated if it is over 2048 bytes. If this occurs you will need to use the
profile APIs (either server, client or entity APIs) to retrieve the full profile.
The PlayStream event which triggered the script.
A boolean that indicates whether a PlayStream event is sent as part of the function being executed
The functions arguments used when calling the script
// Models via Player PlayStream event, entering or leaving a
// player segment or as part of a player segment based scheduled task.
public class PlayerPlayStreamFunctionExecutionContext<T>
{
public PlayFab.CloudScriptModels.PlayerProfileModel PlayerProfile { get; set; }
public bool PlayerProfileTruncated { get; set; }
public PlayFab.CloudScriptModels.PlayStreamEventEnvelopeModel PlayStreamEventEnvelope { get; set; }
public TitleAuthenticationContext TitleAuthenticationContext { get; set; }
public bool? GeneratePlayStreamEvent { get; set; }
public T FunctionArgument { get; set; }
}

public class PlayerPlayStreamFunctionExecutionContext : PlayerPlayStreamFunctionExecutionContext<object>


{
}

Use the context model when executing via an Entity PlayStream


Events, entering or leaving an entity segment or as part of an entity
segment based scheduled task.
When executing script through Entity PlayStream Events, entering or leaving an entity segment or as part of a
entity segment based scheduled task the context that is provided includes the following information:
The Entity Profile
The PlayStream event which triggered the script.
A boolean that indicates whether a PlayStream event is sent as part of the function being executed
// Models via Entity PlayStream event, entering or leaving an
// entity segment or as part of an entity segment based scheduled task.
public class EventFullName
{
public string Name { get; set; }
public string Namespace { get; set; }
}

public class OriginInfo


{
public string Id { get; set; }
public DateTime? Timestamp { get; set; }
}

public class EntityPlayStreamEvent<T>


{
public string SchemaVersion { get; set; }
public EventFullName FullName { get; set; }
public string Id { get; set; }
public DateTime Timestamp { get; set; }
public PlayFab.CloudScriptModels.EntityKey Entity { get; set; }
public PlayFab.CloudScriptModels.EntityKey Originator { get; set; }
public OriginInfo OriginInfo { get; set; }
public T Payload { get; set; }
public PlayFab.ProfilesModels.EntityLineage EntityLineage { get; set; }
}

public class EntityPlayStreamEvent : EntityPlayStreamEvent<object>


{
}

public class EntityPlayStreamFunctionExecutionContext<TPayload, TArg>


{
public PlayFab.ProfilesModels.EntityProfileBody CallerEntityProfile { get; set; }
public EntityPlayStreamEvent<TPayload> PlayStreamEvent { get; set; }
public TitleAuthenticationContext TitleAuthenticationContext { get; set; }
public bool? GeneratePlayStreamEvent { get; set; }
public TArg FunctionArgument { get; set; }
}

public class EntityPlayStreamFunctionExecutionContext : EntityPlayStreamFunctionExecutionContext<object,


object>
{
}

NOTE
You can download the full CloudScript using Azure Functions helper class.
Tutorial: Local debugging for Cloudscript using
Azure Functions
5/24/2022 • 2 minutes to read • Edit Online

With Azure Functions, you can now test and debug your CloudScript code locally. After you have completed this
tutorial, you can run your local Azure Functions app under the debugger (e.g. in VS Code or Visual Studio), set
your breakpoints and run your game client.
In this tutorial you learn how to:
Add an implementation of ExecuteFunction to your local Azure Functions app
Add a settings file to tell the PlayFab SDK to call that local implementation from your game

Prerequisites
Currently local debugging is supported in the following SDKs:
PlayFab C# SDK
PlayFab Unity SDK
Unreal 4 Marketplace PlugIn for PlayFab

Add a local implementation of ExecuteFunction


For C# Azure Functions apps
To get the local implementation of ExecuteFunction set up in your C# Azure Functions app, add the
ExecuteFunction.cs file to your local Azure Functions app.
Required environment variables for local implementation of ExecuteFunction
Add the following settings to your local.settings.json file:

NAME VA L UE

PLAYFAB_TITLE_ID Your title ID, in hex form

PLAYFAB_DEV_SECRET_KEY Secret key for your title. You can find your secret keys in
Game Manager by clicking on the gear icon to the right of
your title's name and going to Title Settings > Secret
Keys .

For example:

{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "...",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"PLAYFAB_TITLE_ID": "B55D",
"PLAYFAB_DEV_SECRET_KEY": "AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMM"
}
}
Configure PlayFab SDK to call local ExecuteFunction implementation
To tell the PlayFab SDK to redirect ExecuteFunction API calls to your local implementation, add a file called
playfab.local.settings.json to one of two places:

The temporary directory on your machine


On Windows, this is the TEMP environment variable
On Linux/Mac, this is the TMPDIR environment variable
The directory of your game executable
Set the content of the file as follows:

{ "LocalApiServer": "http://localhost:7071/api/" }

When you would like to stop local redirects and make ExecuteFunction call the PlayFab API server, simply delete
the playfab.local.settings.json file.

Additional resources
Azure Functions has a great guide on how to test and debug your Functions locally.
Here are some highlights from the above document.
Make sure that your Azure Functions Core Tools are installed
Configure your local settings file. For more information, Develop Azure Functions by using Visual Studio
Code
Set a break point in your code
Select F5 to start debugging
Tutorial: Debugging CloudScript using Azure
Functions with Visual Studio Code
5/24/2022 • 2 minutes to read • Edit Online

If you are using Visual Studio Code, you can use the Azure Functions extension to list your Azure Functions
applications and there is a Start Streaming Logs option:

The logs then show up in the Terminal Window in VS Code as your function runs. You can also get the same
under Logs using the Connect to Log Stream… option:
Tutorial: Debugging CloudScript using Azure
Functions with Visual Studio
5/24/2022 • 2 minutes to read • Edit Online

If you are using Visual Studio, a similar UX is available in Cloud Explorer:


Tutorial: Debugging CloudScript using Azure
Functions in the Azure portal
5/24/2022 • 2 minutes to read • Edit Online

If you are editing your Azure Functions using the Azure portal, you can get logs directly in the portal.
To find the logs you can use the following steps:
1. Open the Azure portal
2. Navigate to your Azure Functions app
3. Select Platform features
4. Select Log Streaming under the Monitoring section

The portal opens a page that displays the debug output:


Actions and rules
5/24/2022 • 2 minutes to read • Edit Online

Use PlayStream Rules to react to PlayStream events in real time. A Rule consists of:
Only one Trigger
An optional list of conditions
One or more actions to take when that trigger is activated.
For example, if you want to send a reward to your players, and send a them a notification when they have more
than 10,000 XP you could:
Define a Segment for your users called “High XP Players”, and set the criteria as XP >= 10,000 .
Create a rule that is triggered by the PlayStream event of those players moving into the High XP Players
segment.
Set two actions for that rule:
1. Grant virtual currency to the player in the segment.
2. Send a push notification to congratulate the player and let them know what they've received.

Links
Actions & Rules quickstart
Actions & Rules tutorials
Actions and rules quickstart
5/24/2022 • 2 minutes to read • Edit Online

A PlayStream rule allows you to react to a subset of one type of PlayStream events in real time.

Requirements
Game Manager quickstart
Using player statistics (contains information that can help you with the example in this tutorial).
A quick glossary of relevant terms:
PlayStream : The group of features that make up the PlayFab Event pipeline.
A PlayStream Event is a JSON-formatted string describing an event about a Player or Title.
PlayStream Events have a maximum size based on your Automation feature tier.
Rule : Performs extra logic in response to one type of PlayStream Event in real time.
The sum of: One Event Trigger , an optional list of Conditions , and an optional list of Actions .
Trigger : The name of the Event which activates this Rule.
Condition : A content filter for Rules and other PlayStream features.
Performs a very lightweight evaluation of the PlayStream event JSON object, and skips events that
don't match requirements.
Action : The contextual work to be done on the appropriate entity.
A rule consists of exactly one Trigger, an optional list of Conditions, and typically at least one Action (not
required, but quite useless without it).
Triggers, Conditions, and Actions are also part of other systems: bulk actions and tournament leaderboards.

Example Case: Count custom events from the client


In the example presented below, we post the following custom event from the client.

public void WriteEvent() {


PlayFabClientAPI.WritePlayerEvent(new WriteClientPlayerEventRequest {
EventName = "ForumPostEvent",
Body = new Dictionary<string, object> {
{ "Subject", "My First Post" },
{ "Body", "My awesome Post." }
}
}, LogSuccess, LogFailure);
}

In this case, the client is manually reporting a custom ForumPostEvent (this does not currently correspond to any
Automatic Event in PlayFab or supported partners)
We will use a PlayStream Rule to count the number of times that a Player reports a forum post in this way.
Requirement : Your game must already be posting Events of this type before the Game Manager GUI will allow
you to create a Rule triggering on it.
Go to your Game Manager :
Navigate to your Title .
Select Automation .
Go to Rules .
Select New Rule .

Let's evaluate the New Rule in this example piece by piece:


title.6195.ForumPostEvent
6195 is the title used in this tutorial. Your titleId will match your own Title.
ForumPostEvent is the event name used in the code for this example case.
This line will only be available if you have recently posted at least one ForumPostEvent in your Title.
The Conditions used specifically in this example, has minimal use.
However, it does demonstrate filtering our Custom Event if the Body key is mapped to Invalid string
in our Body dictionary.
Filters are optional, and should remove irrelevant players from your Rule.
The chosen Actions in this case increments a statistic counter by one.
Requirement : The Forum Posts statistic must be defined under Leaderboards in the Game Manager.
In the Game Manager PlayStream Debugger (shown below), you can watch as the trigger takes effect.

As you can see, the custom ForumPostEvent automatically triggers the statistic that we set under Actions for our
new Rule.

Advanced: CloudScript Actions


Many of the built-in actions in PlayFab are fairly simple, and might not give you the full power you need. That's
why we allow you to fully customize the action logic with CloudScript.
Let's edit the Rule .
Remove the Condition .
Set the Action to Execute CloudScript .
Select the Save Action button.
Now, if we post a new ForumPostEvent , we will see a CloudScript execution.

Writing your CloudScript to react to PlayStream Rules is an advanced topic covered in our tutorial: using
CloudScript actions with PlayStream.
Actions & Rules Tutorials
5/24/2022 • 2 minutes to read • Edit Online

These tutorials show you how to make use of CloudScript with PlayStream hooks to perform actions on specific
player segments.
Bulk Actions for an entire player segment
Using CloudScript actions with PlayStream
Bulk Actions for an entire player segment
5/24/2022 • 5 minutes to read • Edit Online

This tutorial walks you through the steps needed to create a task to perform one or more actions on every
player in a segment.
Tasks are a vital part of live operations for any game. They give you a powerful set of tools for engaging with
your players.
Examples might include:
Give a special New Year’s gift to all players who logged in during the last 2 weeks.
Reward players who spent money in the last week (based on spending tiers), where the more money they
spent, the more valuable the gift.
Fixing corrupted Player state for all players affected by a recent game bug.
In this tutorial, based on our Unicorn Battle Sample App , we will grant a special gift to all players with more
than 2,725 XP .

Prerequisites
You will need to install the Unicorn Battle Sample App to run this tutorial. You can read more about it in our blog,
or go directly to the GitHub repository and follow the instructions there.

You will want to play several battles, in order to level up your character to at least Level 2 , which you reach at
2,725 XP points.
Step 1 - Create the segment
The first step is to create the segment that defines the group of players who will be affected by this action. In this
case, we need to create the High XP Segment , defined as all players who have more than 2,725 XP :
Select PlayStream from the menu on the left.
Choose the Segments tab.
Then select the New Segment button.
Make the Segment Name : High XP Players .
Define it as Player , where the Statistic Value called Total_XP Gained is greater than 2725 .

NOTE: The current scheduled task system can process 10-15 tasks per second per segment. When
designing your segments plan ahead for how large they will be and how long the task execution will run.
There is no limit for how long a task can run but if they task needs to be executed in a specific timeframe
then the segment needs to be sized properly.
Step 2 - Create a task for this segment
Select the Segments tab.
Then select RUN TASK …

This will take you to the Create Task view in the Ser vers ->Tasks tab, and will pre-populate various fields
based on your selected segment.
Step 3 - Add actions to the task
Next, you can finish setting up the task.
Change the name to Reward High XP Players
Add this description: Give a gift to Players who are level 2 or higher .
Select ADD ACTION
Type in Grant vir tual currency in the field provided.
Vir tual Currency code: GM (short for Gems ).
Amount: 20
Leave the scheduling set to Manually for now.
Select the SAVE AND RUN button to run the task.

Step 4 - Monitor your task


The Tasks view will show you your running task. Initially the task status will be InProgress , but it will quickly
change to Succeeded , since the segment is small.

Now, let's check out the task execution detail. Select the completed task in the previously run Tasks list. You will
see important information, such as:
How many players were processed.
When the task started.
How long it took to complete.
The parameters it had when it was launched.
Who ran it.
If it was scheduled manually, etc.
If the task is still in progress, you can check the Task Instance Detail view for the progress, and see the
estimated time remaining.
To verify that the task ran successfully:
Navigate to the Players tab.
Select your Player .
Then choose the Event Histor y tab.
The most recent event in the list should be a player_vir tual_currency_balance_changed , which should
show your Player ’s gems increasing by 20 .

NOTE
You can expand this event to see the details.
What’s next
This tutorial has introduced you to the steps involved in performing an action for every player in a segment, but
there’s a lot more you can do with tasks.
Here are a few ideas for other things you can try...
Schedule your tasks
You don’t need to run tasks manually - you can schedule a task to run automatically on a recurring basis. For
example, you could create a segment of all players who played the game in the last 24 hours, then run a
scheduled tasks each day to give those players an XP boost.
Run CloudScript for each player
The most powerful use of bulk actions is running an arbitrary CloudScript function for each player. This
CloudScript can do anything the PlayFab server API can do - grant items, currency, inspect and change player
data, and so on.
For example, imagine you have an event leaderboard that resets every week, and you want to go through all
players and give a reward based on the value of the last event before it reset. The example provided below is
using Unicorn Battle .
1. Create a new stat Event_QuestsCompleted , that resets weekly and uses the aggregation method Last .

2. Create a new PlayStream action that increments this Event_QuestsCompleted stat, whenever
Total_QuestsCompleted is changed.
3. Write a CloudScript function to be called by a Bulk Action task, which will go through players and give
rewards based on the last value.

// this function will be called as a bulk action by a scheduled task for players in a segment
handlers.GiveTieredReward = function (args, context) {
var profile = context.playerProfile;

var statVersion = 0; // set to whatever version you need to use

var getStatRequest = {};


getStatRequest.PlayFabId = profile.PlayerId;
getStatRequest.StatisticNameVersions = [{ "StatisticName": "Event_QuestsCompleted", "Version":
statVersion }];

try {
getStatRequest.PlayerResult = server.GetPlayerStatistics(getStatRequest);
} catch (e) {
};

if (getStatRequest.PlayerResult && getStatRequest.PlayerResult.Statistics.length > 0) {


getStatRequest.lastScore = getStatRequest.PlayerResult.Statistics[0].Value
}

if (getStatRequest.lastScore && getStatRequest.lastScore > 2) {


// give gift to all players with more than 2 quests completed in last event
// in a real event we would want to use a lookup table of gifts
// but here we are just hard-coding it
var giftRequest = {};
giftRequest.PlayFabId = profile.PlayerId;
giftRequest.ItemIds = ["CrystalKey"];
giftRequest.grantResult = server.GrantItemsToUser(giftRequest);
return giftRequest;
} else {
return getStatRequest;
}
}
4. Set the new CloudScript version to Live , and create a new task that calls the GiveTieredReward function
for all players. Don't forget to Save and Run the task.

5. You should notice events from this task appear in the PlayStream event debugger.

6. You can select any player triggered action executed CloudScript event (by selecting the time stamp), and
see the detailed result of CloudScript execution for each player. This includes useful diagnostic
information such as the snapshot of the player profile at the time of the CloudScript execution.
Using CloudScript actions with PlayStream
5/24/2022 • 4 minutes to read • Edit Online

When a CloudScript handler is launched from a PlayStream action, that handler has access to additional data on
why it is being run - the context - which you can use to drive your server-side logic.
This tutorial walks you through what all is available in the context, and how to make use of it in your CloudScript
handlers.

CloudScript basics
The key to getting the most out of CloudScript is knowing how to work with the inputs you have available –
namely, the args and context for your handler.
For example, here’s the helloWorld example from the starter CloudScript, loaded as Revision 1 in all newly
created titles (also available in our GitHub, shown below).

// This is a CloudScript function.


// "args" is set to the value of the "FunctionParameter" parameter of the ExecuteCloudScript API.
// "context" contains additional information when the CloudScript function is called from a PlayStream
action.
handlers.helloWorld = function (args, context) {

// The pre-defined "currentPlayerId" variable is initialized to the PlayFab ID of the player logged-in
on the game client.
// CloudScript handles authenticating the player automatically.
var message = "Hello " + currentPlayerId + "!";

// You can use the "log" object to write out debugging statements. It has
// three functions corresponding to logging level: debug, info, and error. These functions
// take a message string and an optional object.
log.info(message);
var inputValue = null;
if (args != null && args != undefined)
{
inputValue = args.inputValue;
}
log.debug("helloWorld:", { input: inputValue });

// The value you return from a CloudScript function is passed back


// to the game client in the ExecuteCloudScript API response, along with any log statements
// and additional diagnostic information, such as any errors returned by API calls or external HTTP
// requests. They are also included in the optional player_executed_cloudscript PlayStream event
// generated by the function execution.
return { messageValue: message };
}

This example demonstrates the common use case of calling CloudScript from a client, via ExecuteCloudScript. It
checks for an argument passed in with the key inputValue , and uses the value for that key as part of the text
returned in the debug log info for the execution.

The context input parameter


However, it’s also possible to call a CloudScript as a result of an event in PlayStream, via a Rule (Automation -
>Rules ), a Segment Enter/Exit Action (Players ->Segments ), or the Task Service (Automation ->Tasks ).
When you do, the context passed in to the function provides all the information you’ll need to take the
appropriate action.
To read about the basics of how PlayStream events work, see our blog Introducing PlayStream, and for a list of
PlayStream event types and their properties, see our PlayFab API Reference.
To view this action, have a look at the handlePlayStreamEventAndProfile handler from the same sample
CloudScript.

// This is a simple example of a function that is called from a


handlers.handlePlayStreamEventAndProfile = function (args, context) {

// The event that triggered the action.


// For a list of event types, see our PlayFab API documentation.
var psEvent = context.playStreamEvent;

// The profile data of the player associated with the event


var profile = context.playerProfile;

// Post data about the event to an external API


var content = JSON.stringify({user: profile.PlayerId, event: psEvent.EventName});
var response = http.request('https://httpbin.org/status/200', 'post', content, 'application/json', null,
true);

return { externalAPIResponse: response };


}

In the case of a PlayStream-triggered CloudScript call, the context contains 3 elements that can be used to drive
your server-authoritative handler's logic.
1. There’s the playStreamEvent , which you can see in the example code above. The playStreamEvent
contains the complete event which triggered the handler as a JSON object, with all the parameters you
see in the PlayStream event documentation. So for example, if you set up a rule in your title that called
handlePlayStreamEventAndProfile on any player_logged_in event , playStreamEvent.EventName would be
player_logged_in , etc. (here’s the complete set of parameters for that event).

2. Next, there’s the playerProfile , also shown in the previous example. This contains information about the
player that triggered the event. You can find all the details of the profile parameters here, but among
other things, it contains the complete set of statistics for the player in your title, as well as any custom
tags you have assigned to the player, so that you can use that data for very rich decision-making.
3. The last element of context is triggeredByTask . Unlike the first two, which are set when using Rules and
Segment Enter/Exit triggers, triggeredByTask is only applicable when the handler is running as a result of
a task, whether manual or on a timer. It contains only two parameters:
Name – The unique name you gave your task when you created it.
ID – The unique identifier automatically generated by PlayFab for your task.
For a task run against a user segment, you’ll also have the playerProfile , but you won’t have a
playStreamEvent .

And for a task that’s simply run against your game but without any segment, there won’t be a playerProfile ,
since the intent is to run something more general, like setting some title data for an event.
So name is the element you’ll want to use to use in your handler’s code flow, to determine the appropriate
action to take.

PlayStream plus CloudScript


In many ways, CloudScript handlers triggered by PlayStream actions have even more potential functionality
than those triggered directly through calls to ExecuteCloudScript , since there’s a rich set of data made available
via the context.
This gives you the ability to update your handlers post-launch with additional logic that makes use of elements
of the event or player profile that you hadn’t originally anticipated, without needing to update your client code
in any way.
In addition, we’ll continue to make additions to the player profile in future updates of the PlayFab service, which
will provide even more options for server-side logic.
Scheduled tasks
5/24/2022 • 2 minutes to read • Edit Online

Scheduled tasks are a way to automate common game operation routines. Some examples are:
Updating Title Data to reflect changes for a current event.
Injecting virtual currencies into the game economy daily.
Modifying prices in a store according to the time of day.
Reaching out to lapsed players and encouraging them to re-engage.
Automated tasks can take predefined actions or execute CloudScript, which enables any custom server-side
functionality you want to implement.

Links
Scheduled Tasks quickstart
Scheduled tasks quickstart
5/24/2022 • 3 minutes to read • Edit Online

This quickstart shows you how to create a task that runs on a schedule. There are many game operation
routines that can be automated using a scheduled task, such as:
Modifying prices in a store according to the time of the day.
Updating title data to reflect changes for a current event.
Injecting virtual currencies into the game economy daily, etc.
In the example used in this quickstart, we'll show you how to modify a game variable called rareDropRate in
the title data at 12:00 UTC, and only on weekend days.

Step 1 - Prepare the CloudScript


In the Game Manager :
Select Automation in the menu to the left.
On the CloudScript Revisions tab add a new CloudScript function called adjustRareDropRate with a simple
call to the SetTitleData API as shown in the code snippet and image below.

NOTE
For the sharp-eyed, don’t worry - there’s a bug in there on purpose. Make sure you deploy the new revision, so that it is
live in your game.

You can learn more about using CloudScript in our CloudScript quickstart, and in documentation for the method
ExecuteCloudScript.

handlers.adjustRareDropRate = function(args) {
// Tutorial demo CloudScript
serverAPI.SetTitleData({
"Key": "rareDropRate",
"Value": args.dropRate
});
}
Step 2 - Create a scheduled task
Now select Ser vers from the menu to the left.
Go to the Scheduled Tasks tab.
Select New Scheduled Task on the upper-right corner of your screen.
This will bring up the Create Task view.
In the Type of task field, choose Run a CloudScript function .
Below that, you’ll be able to pick a function from the currently deployed revision of CloudScript, and specify
arguments to pass in.
Choose the adjustRareDropRate Handler that you wrote in the previous step.
To set the schedule for this task:
Select On a schedule (UTC) under the SCHEDULE header.
A simple schedule builder lets you choose when the Task should run (every hour, day, week, etc).
For this example, we would like an advanced schedule, where we can specify which days of the week to run
the task.
So select CRON EXPRESSION .
The highly customizable Cron Expression allows you to build a very complex schedule, though it’s important to
note that we currently only allow schedules whose occurrences happen on 5-minute marks of the hour.
For example, you may specify a task to run on the 5th, 10th, 25th, or 50th minute of the hour, but you may not
specify a task to run on the 3rd, 11th, or 46th minute of the hour.
If you'd like to learn more about Cron Expression, crontab.guru provides rich information and an interactive
expression builder.
In this case, we want the task to run at 12:00 UTC on Saturdays and Sundays, which would be 00 12 * * 0,6
(zero minutes past twelve o’clock, every Sunday and Saturday).
Finally, make sure you save the new task before moving on to the next step.

Step 3 - Test the task


On the Tasks view (Ser vers -> Tasks ), we can see that the next run of the newly created task is on the
following Saturday - as expected.
So, if it’s currently Tuesday, then the next scheduled runtime would be 4 days away. To test the task now , select
the Adjust rare drop rate task and choose RUN TASKS .

Step 4 - Check the results of the test run


Unfortunately, the task run has failed. Select the task instance to see what went wrong.

The Task Instance Details view provides diagnostic information on why the task failed.
In this case, it’s pointing out that the call to ser verAPI.SetTitleData is incorrect. It should really be
ser ver.SetTitleData (for an explanation, see the Intermediate: Calling the Ser ver APIs section of the
Writing Custom CloudScript tutorial).
There is other important information on the Task Instance Details view as well - such as the start and end
times, the function that was called, any arguments passed in, the full CloudScript execution result, and more.
Step 5 - Test again (successfully)
Go ahead and fix the error we found in Step 4. The correct code snippet is shown below.

handlers.adjustRareDropRate = function(args) {
// Tutorial demo CloudScript
server.SetTitleData({
"Key": "rareDropRate",
"Value": args.dropRate
});
}

And now, repeating Step 3, your final test run is successful.

To confirm success:
Select Content in the menu to the left.
Go to the Title Data tab.
Verify that the Title Data entry was actually set.
PlayStream
5/24/2022 • 4 minutes to read • Edit Online

PlayStream offers the following features to developers:


An event pipeline - That unifies the entire data flow from your game into a single data stream. The PlayFab
Game Services will automatically insert events into PlayStream, and you can add custom events using our
new WriteEvent API client and server methods. Our Marketplace Add-ons will also generate events
automatically. Events are managed as JSON data.
A real time rules engine - That can evaluate complex rules in response to incoming events through
PlayStream, and trigger a variety of actions, including CloudScript.
A real time segmentation system - That can group players into segments based on a variety of player
properties. Segments are calculated in real time and are always up-to-date. Actions may be triggered
automatically as players enter or exit segments.
A real time visualization of event data - That includes a real-time event debugger.
The ability to send some or all of the events to external web ser vices via webhooks - These can be
configured automatically by installing Marketplace Add-ons, or configured manually to send events to your
own servers.
An event archive - Where you can filter, search, and view historical events - including event delivery
history.
Let’s look at these features in more detail.

NOTE
PlayStream now offers support for entity events as well as classic PlayStream events. To learn more, please reference the
PlayStream with entity events article after you finish this one.

PlayStream event pipeline and monitor


The easiest way to see the event pipeline in action is through the PlayStream Debugger. You’ll notice the monitor
as soon as you click on the PlayStream Monitor tab for your game.

The PlayStream monitor is a real time stream of all the events for your game, including any custom events you
choose to send, using our WriteEvent API methods.
This is immensely valuable during development, as it gives you a way to immediately see what’s happening on
the back end as you test out your client- and server-side code. It also links you straight to the player accounts, so
that you can check them against the game logic you’re working on.
There are several selectable fields in each event. If you select the “(i)” information circle, you will see the raw
event JSON data.

You can also select the player’s ID to jump straight to the player’s profile. Certain other events also have
selectable fields.

Player segmentation and actions


Using those events, you can set up segments which define players within your users, based upon most player
properties. This all happens in real time - so there should be no perceptual lag, even at large scale.
If you can tie an event to the thing you want to use as a differentiating factor, you can make a segment for it. And
segments will apply retroactively to all players, based on the data in their profiles -- so if you define a segment
of players where XP > 3,000, then every player with XP > 3,000 will now be in that segment.
This particular segment will be evaluated anytime the statistic called "Total_XPGained" changes. If the condition
(> 3000) evaluates to true, then the player will enter the “High XP Players" segment, and the corresponding
action(s) will be triggered -- in this case, it will send a push notification, and grants gold to the player.
You can also trigger different custom actions when the player leaves a segment, allowing you to make any other
changes needed as a result.
There are a variety of basic actions available, including granting an item to the player, granting virtual currency,
changing a statistic, banning a player, sending a player an email or sending a Push notification. You can also
trigger custom CloudScript to be run instead.

Rules and Actions


The same action system shown above can also be utilized to respond on specific events coming from your
game. For example, the rule shown below demonstrates how when a custom event (Client_StoreVisit ) is seen,
the player receives some virtual currency, and receives a push notification thanking them for their visit.
Using rules and actions, you can affect LiveOps behaviors in your game without making any changes to the
game client.

Webhooks
You can also set up Webhooks, such that some or all of the events going through PlayStream will get pushed out
to an external service.
For example, you could use the feature shown below to call your own back end server on any player login.
PlayStream Webhooks are POST calls to your provided endpoint, which pass along all the data for the event in
the body of the call. Using this mechanism, you could then enable additional custom actions on your real-time
data, using your own custom services.

Event History
You can also access a historical archive of events. By default, events are kept for a certain period of time that
depends on your service tier. You can view the event history in two places - you can view all events for your title
in the PlayStream Event Histor y tab, or only events for a particular player on that player’s PlayStream tab.
You can select the arrow to the left of a particular event to see details only for that event, including its delivery
history. For example, the event shown below has been delivered to three different Marketplace Add-ons -
Appuri (both legacy and current), and Segment.com . You can click on the event name to filter the list of events
by all events of that name.
Custom Tags
The Custom Tags feature allows game developers to further enrich their standard PlayStream events with
business specific metadata.
This is a quality of life feature designed to make building on top of PlayFab easier and more extensible.

Getting Started With PlayStream


PlayStream with entity events
Actions and Rules
Segmentation
Generating PlayStream Events
Custom Tags
PlayStream Event Reference
Using Custom Tags with PlayStream Events
5/24/2022 • 3 minutes to read • Edit Online

Custom Tags are a collection of key-value-pairs that studios can optionally include with every API request. They
are useful to enrich the standard PlayStream events with more studio specific metadata (e.g. build number,
external trace identifiers, etc.).
Custom Tags extend the ways in which you can use PlayStream events. The basic PlayStream schema is fixed and
lacks extensibility but allowed us to build common metrics and analytics. The fixed nature of the schema limited
game studios' ability to customize their data in an efficient and economic manner, as well as their ability to
collect specific data points. Custom Tags provide a way to extend the schema to allow greater flexibility and
functionality.

What can you do with Custom Tags?


There are many things you can accomplish using Custom Tags. Here are some suggestions, but feel free to be
more creative when using them.
Automation
PlayStream metadata can act as criteria that trigger certain events. When a task needs to be accomplished, a
PlayFab customer can set up a rule to say “if [Custom Tags] satisfies xyz requirement, then fire action A.”
You can integrate CloudScript with Custom Tags to achieve automation. CloudScript Actions and Rules allow you
to fire off events automatically based on certain criteria.
For example, if your game studio is investing in performance marketing for your game, and you are running a
variety of different marketing campaigns to acquire new players, you can now track the marketing campaign
that acquired a player and add that campaign ID to all PlayStream events. Then you can use that campaign ID to
automate processes. For example, if your ad promised “1,000 free gold coins for signing up” then send the “new
player” event and use marketing campaign to decide what incentive to give the player. E.g., ‘if marketing
campaign = ‘FREE_GOLD_COINS’ then give player 1,000 gold coins.
Telemetry
PlayStream metadata can assist with data collection and analysis. For example, you can send Custom Tags as
part of your PlayStream event data from non-PlayFab services and be able to keep track of it as it flows through
the data pipelines. If you already have your own analytics system (e.g. based on some identifier), you can easily
integrate and merge new data by passing that identifier in Custom Tags as part of your PlayStream events.
You can include campaign IDs or other analytical identifiers to analyze revenue, determining which campaign
generated the highest new player acquisition, revenue stream, or customer value.

Data flow
Once Custom Tags are received from API request, the data becomes part of the PlaySteam event, which then
flows through the PlaySteam pipelines to be stored in Kusto, PlayFab's backend data warehouse.

Limitations
Custom Tags have the following restrictions:
No more than 10 key value pairs
Each key string cannot be more than 64 utf8 chars
Each value string cannot be more than 128 utf8 chars
Only supported with API calls (i.e. not supported by the Game Manager UI)

Getting Started
The following sample request show you how add Custom Tags to your JSON request. The CustomTags follow the
relevant PlayStream events as they flow through the data pipelines and you are able to access this data later for
actionable and analytical purposes.
Sample Request

POST https://titleId.playfabapi.com/Server/WritePlayerEvent
{
"PlayFabId": "{{PlayFabId}}",
"EventName": "player_defeated_enemy",
"Timestamp": "2016-03-07T00:00:00Z",
"Body": {
"Enemy": "guardian",
"Damage": 5,
"Coordinates": {
"X": 123.4,
"Y": 543.2
}
},
"CustomTags": {
"correlation_id": "123abc",
"build_number": "1.0.0.0",
"platform": "iOS"
}
}

Sample Response
Adding Custom Tags does not alter the response you receive from the call to the endpoint. The response after
you add the CustomTag node is identical to the one you receive when the node is not present.
PlayStream with entity events
5/24/2022 • 2 minutes to read • Edit Online

PlayFab has introduced the entity event model , a new event model that corresponds to the entity
programming model . An entity refers to any PlayFab concept that contains data. That can be a player, title,
character, group, etc.
In the classic event model, there existed different events and APIs for each type of entity. For example, when
creating a new entity you'd see an event like group_created , character_created , or player_created depending
on what type of entity was created. Under the entity event model, there's only a single event, entity_created , to
encompass all of the above.
With the new entity format, we were able to simplify the amount of different APIs and events that exist. You'll
continue to see classic events alongside entity events in the PlayStream monitor in order to support existing
titles as we finish migrating to the new event model.
Entity events support the following PlayFab features:
Batches of events - Write multiple entity events to PlayStream at once with the WriteEvents API.
A real-time rules engine - Set up rules that react in real time to entity events flowing through PlayStream,
and trigger a variety of actions. PlayFab supports the following actions on entity events:
Run custom CloudScript (including CloudScript with Azure functions)
Send emails
A real-time debugger - See entity events appear in the PlayStream monitor alongside classic events.

NOTE
Currently Playstream does not support creating rules for events with names longer than 40 characters.

Entity events are also supported for data and analytics features that allow you to discover pertinent information
about your game:
PlayFab Insights - Have the tools to examine all of your event data together, both classic and entity events.
Rewarded ads
5/24/2022 • 2 minutes to read • Edit Online

Rewarded video ads let your players choose to watch a short video in exchange for an incentive (usually in-
game currency, special items, etc). They are a great way of generating revenue, especially for free-to-play games.

What is an ad placement?
An ad placement consists of a list of defined rewards to grant once a player watches an ad. You control the odds
of a player recieving a randomized reward by giving each reward a different weight. Additional customization is
available by setting a limit on the number of times a player can be rewarded for watching an ad. For example,
it's common to set a limit of 3 times per day, per player. This incentivizes players to return to your game day
after day.
Addtionally, leverage player Segments to set overrides that allow different groups of players to receive different
rewards. For example, reward your VIP players with a special item while other players are rewarded with
currency.

Why use rewarded ads?


Rewarded ads create incentives for players to engage regularly with your game and offer them greater control
over how they choose to engage with in-game advertising. It can result in players spending more time with the
game and promote higher retention.
Quickstart: Set up an Ad placement
5/24/2022 • 4 minutes to read • Edit Online

Rewarded ads are a way of incentivizing your players to watch video ads in exchange for an reward. Each ad
with its associated rewards is considered an ad placement. In this quickstart you will set up an ad placement and
configure rewards for it.

Prerequisites
A PlayFab developer account.
An Application ID and Advertising Unit type from your ad provider.

Set up an Ad placement
In the Rewarded Ads tab, the first thing you'll see is the main dashboard for your ads. Here you'll find basic
KPIs for your ads, along with a graph showing your recent ad events (they also show up in the PlayStream
Debugger. At the top, select Placements .
Ad placements are the most fundamental part of the system. Think of a single placement as an "ad position": the
type of ad that will be displayed (banner, video, etc.) and at what point in the game the player will see it (level
interstitial, as a result of clicking on a "show me an ad", etc).
In the upper right corner, select New Ad Placement . Name your placement whatever you like, and enter the
Application ID and Advertising Unit type from your ad provider. If you're uncertain as to where to locate the
Application ID and Advertising Unit type for your specific provider, let us know and we can work with you to
identify them.

Add rewards
Now you'll need to add your specific rewards. For each possible reward for this placement, select New Reward .
Give your reward a name and enter any description text and asset package URL you want returned to the client
when the specific reward is given. Then, under Actions , select Add Action . Just as you can with regular
PlayStream actions, you can take a number different actions right now - running a Cloud Script handler, granting
items, etc. Usually, you'll be granting virtual currency or items here, but if you want to make use of the other
action types it'll all be processed the same way it is for a normal PlayStream action trigger.
After you have a couple of rewards defined, give each one a weight to set up the random distribution. If you've
defined Segments for your title, you can also set overrides in the Segment Assignment tool below Rewards .
For example, if you have a certain group of players that you want to always get a specific reward, set that
segment to that reward in the assignment list. The segment assignments are in priority order, so the first
segment that matches one for the current player is the one that is used. The following example defines an ad
placement that provides free gems 0% of the time, bonus experience points 30% of the time and a "key" item
70% of the time.
In the example we use Segment Assignment to provide rewards in a priority order. If the player is in the "High
XP Players" group, the normal random selection is made. But if the player is in the "VIP players" segment, we
grant that player the "gems" reward.

TIP
Consider creating a segment for players who are watching an ad for the first time, and grant them one of your more
desirable rewards. This can help incentivize your players to continue engaging with rewarded ads, and lead to a higher
retention rate overall.

Finally, you have the option to limit the number of times the player can be rewarded for an ad. In our example,
we limited this to 4 times per day, per player (daily resets on this counter occur at 00:00 UTC). You can have the
limit reset daily, hourly, or every two hours.

Retrieving the Ad Placements


After defining at least one ad placement, you can query for a list of available placements using
Client/GetAdPlacements. Specify an Identifier in the call to ensure that you only get information on the given
placement. To filter for a specific placement, you can use either the name you defined for it (above), or the
PlayFab-generated unique identifier for the placement (which you can see in the URL, in the example above).
Otherwise, all available placements for which the player has a valid reward, including the reward for the player,
the number of views currently remaining, and the time to reset the view limit are returned in an
AdPlacementDetails object. When you have selected an ad placement in the client code, make sure to save the
PlacementId and RewardId . You'll be using those for the next two stages.

Reporting Ad Activity
We define four activity states for an ad - "Opened", "Closed", "Start", and "End". As you use Rewarded Ads, make
sure you're calling Client/ReportAdActivityRequest to update the activity state every time your ad SDK reports a
state change.

Rewarding Ad Activity
When your ad SDK reports that the ad view has successfully completed, call Client/RewardAdActivity to trigger
the reward. This call requires the PlacementId and RewardId returned by Client/GetAdPlacements. It first checks
that the reward is valid, then processes it for the player. Items are granted immediately, and the call then returns
a complete set of changes made to the player by the Grant Item, Grant Virtual Currency, and Increment Player
Statistic actions.
Finally, it's important to note that the reward ID is not bound to the player as part of the call to
GetAdPlacements. Based on the weightings you've provided, calling GetAdPlacements multiple times might
cause the reward to change. The call to RewardAdActivity only requires that the reward be valid for the player,
not that it was the last one returned from GetAdPlacements.
Multiplayer with PlayFab
5/24/2022 • 6 minutes to read • Edit Online

Multiplayer is a great addition to many titles, and PlayFab provides several services focused on multiplayer
scenarios:

SERVIC E DESC RIP T IO N

Leaderboards Track and respond to player activity with statistics and


leaderboards.

Entity Groups Create permanent or temporary groups of players and


signal activity.

Matchmaking Deploy custom matchmaking rules to group players quickly

Party Connect players with networking and accessible in-game


chat

Servers Dynamically scale custom multiplayer servers in Azure

While titles can use all of these services in combination, they can be used independently as well, and this is quite
common. For example titles might use PlayFab matchmaking but allocate servers from an alternative
multiplayer server hosting solution. Or games might use PlayFab multiplayer servers for hosting, but use their
own matchmaking system to bring players together.
Increasingly games are building cross-network experiences with players engaging each other from different
identity domains (e.g. Xbox Live players interacting with Steam players interacting with custom identity
systems). PlayFab's services were designed to support cross-progression and cross-network play.

Example multiplayer scenarios


PlayFab is designed to support a variety of multiplayer modes. Below is a list of modes that might be integrated
in a single, fairly sophisticated title. In this section we will briefly suggest how to implement these experiences
using PlayFab services.

UN SO L IC I
T ED
MAX # JO IN - IN -
GA M E OF L EA DERB M ATC H M IN VIT E P RO GRES SERVER
M O DE P L AY ERS O A RD A K IN G B A C K F IL L F RIEN DS S C H AT M O DEL

Single- 1 Yes No No No No No No
player
campaig
n

Coopera 4 Yes No No Yes Yes Yes P2P


tive
campaig
n
UN SO L IC I
T ED
MAX # JO IN - IN -
GA M E OF L EA DERB M ATC H M IN VIT E P RO GRES SERVER
M O DE P L AY ERS O A RD A K IN G B A C K F IL L F RIEN DS S C H AT M O DEL

In- 8 No No No Yes Yes Yes P2P


Game
par ties

Casual 8 Yes Yes Yes Yes Yes Yes P2P


small
sessions

Casual 32 Yes Yes Yes Yes Yes Yes Cloud


large Server
sessions

Competi 8 Yes Yes No Yes No Yes Cloud


tive Server
small
sessions

Competi 32 Yes Yes No Yes No Yes Cloud


tive Server
large
sessions

Leaderboards and player data


In-game leaderboards can be used to:
1. Store player results to trigger in-game rewards and other gameplay behavior
2. Store and rank player results as a matchmaking input
3. Create in-game ranking experiences, where users can browse the leaderboard and understand their
comparative performance
Leaderboards can augment both single-player and multiplayer modes. For example a campaign leaderboard
might track the number of special items collected by the player, while a multiplayer leaderboard might track
player vs. player competitive wins. PlayFab leaderboards is built to power these experiences, tracking a player
statistic and ranking players using that statistic.
If player results do not need to be shared broadly with other players, player-associated PlayFab Entity data may
be better suited to store this data. A benefit of PlayFab's Entity system is the ability to track cross-network
progression of player's activity and other data across multiple accounts. Changes to PlayFab leaderboards and
data both fire PlayStream events which can trigger custom CloudScript. This allows for highly customizable
responses to player activity in real-time.
Applicable services:
Learn more about Leaderboards
Learn more about Entity data
Learn more about CloudScript
In-game parties and unsolicited join-in-progress
Players often want to commiserate outside of proper gameplay and your title may support this through an in-
game guild or party experience. PlayFab Entity groups and PlayFab Party are designed with these scenarios in
mind.
You can make a PlayFab Entity group for:
1. Players sharing status with their followers
2. Players creating guilds that are long-lived (months or days)
3. Players creating parties that are short-lived (hours or less)
PlayFab Entity groups have built-in flows for controlling access and players requesting group access from the
group's leaders. Groups can be associated with arbitrary file data, so you can allow players to share messages or
post other persistent content to a shared space.
While you can use Entity groups for signaling and other slow data-sharing, PlayFab Party is best suited for real-
time data transfer and chat. A common usage of PlayFab Entity groups will involve players storing PlayFab Party
network descriptors or PlayFab multiplayer server session details to the group's data storage. This sharing of
session information can allow players to join a friend's session unsolicited. If you are using non-PlayFab services
for real-time communication or game hosting, those systems typically have identifying information that you can
similarly signal between players using Entity groups.
PlayFab Entity groups does not have a push notification system for players to be notified of Entity object
changes and requires polling the service to keep updated. Platforms may provide built-in invitation and
presence systems that launch toasts and have other beneficial experiences ( join in progress from the player
profile card) that you should consider integrating if applicable.
Learn more about Entity groups
Learn more about Party
Matchmaking and backfill
Players may want to play with new people they don't know, and balanced anonymous matchmaking experiences
are core to many multiplayer games. PlayFab Matchmaking is designed to get players together quickly using
rules you customize.
When a player or group of players want to play together, one player creates a matchmaking ticket for
themselves or the entire group. PlayFab Matchmaking allows users to be submitted to matchmaking together as
a team, with a join flow that ensures that all players in the group consent to match together. The service also
allows for backfill tickets, which can be used to replace players who leave mid-game. Join in progress and
backfill capabilities are helpful mechanisms to keep casual game sessions as full as possible.
PlayFab Matchmaking is integrated with PlayFab Multiplayer Servers to simplify server allocations for
completed tickets and improve match security. Also PlayFab Matchmaking tickets fire PlayStream events that can
trigger CloudScript, this can help integrate matchmaking with your own multiplayer systems.
Learn more about Matchmaking
Chat
PlayFab Party be used to add real-time voice and text chat to social or gameplay experiences for up to 32
players. PlayFab Party enables a player's presence in multiple networks simultaneously, with customized muting
rules for each network. This provides flexibility to implement channels and complex chat relationships.
Party utilizes Azure Cognitive Services to transcribe player voice chat and synthesize text as speech. This
functionality has several uses, but was primarily designed as an accessibility aide. Party not only transcribes
player chat, but also translates chat in real time. In anonymous matchmaking and international competitive
games, these transcription and translation capabilities make for a more engaging multiplayer experience.
Learn more about Party
Game hosting
Real-time multiplayer games typically select a specific player device to host game state (aka "peer to peer") or
use a dedicated multiplayer server. If hosting a game on a player device, PlayFab Party is an ideal low-latency
device-to-device networking system to synchronize this game state across the session's participants.
It is difficult to scale peer to peer games when the device count grows. While PlayFab Party provides network
encryption and uses relays to protect player IP addresses, having a device operate as host still opens avenues
for cheating.
PlayFab Multiplayer Servers provides simple and efficient scaling of multiplayer across Azure's global cloud.
Using a small server, for example loading 10 sessions of 10 players each on a F2v2 Linux virtual machine, can
efficiently and dramatically simplify your multiplayer design and improve it's reliability compared to a P2P
implementation. Sophisticated multiplayer computation can be achieved by setting a server's build
configuration to allocate more Azure resources to a session, perhaps using 8 or more cores for a 200 player
experience.
Learn more about Party
Learn more about Multiplayer Servers
Multiplayer Servers
5/24/2022 • 2 minutes to read • Edit Online

PlayFab Multiplayer Servers (MPS) is a server hosting service optimized for games. It enables you to
dynamically scale custom game servers according to demand.
Our servers are built on Azure Compute so it is a global distributed cloud service that offers a broad range of
compute capacity.
As a PlayFab customer, you can access our service and use a limited, free quota of multiplayer servers for
product evaluation and testing.

Features
Server infrastructure optimized for hosting multiplayer games
Cloud compute capacity that scales on demand
Multiple ways to manage scaling. Faster response time with the ability to schedule, dynamically, and
programmatically change the number of standby servers
Consistent test and production environment for game servers as they run as containerized applications
Deploy Windows or Linux game servers
VMs are built on global distributed Azure Compute services for low latencies
Full-fledged identity solution with managed end-point protection
Wide range of compute capacities for desired gaming experience
Works well with other PlayFab LiveOps and multiplayer features

How to use the service


These are the typical steps to use PlayFab Multiplayer Servers.
If you are still in the early stages of development but want to evaluate or learn how to use this feature, see
Create your first server. This topic uses our samples to walk you through the process of deploying servers using
our service.
1. Author a game server build
2. Deploy a VM build
3. Scale game servers
4. Measure player latency
5. Request game servers
6. Connect and play

See also
Using PlayFab Multiplayer Servers to host multiplayer games
Create your first server
Terminology
PlayFab Multiplayer Server SDKs
PlayFab Multiplayer Server API reference
Using PlayFab Multiplayer Servers to host
multiplayer games
5/24/2022 • 3 minutes to read • Edit Online

This topic explains how to use PlayFab Multiplayer Servers to host multiplayer game sessions—from creating
game servers that are ready to connect players for a game session to scaling them dynamically to meet
demands.
Using our service, you configure VMs to be automatically spun up globally as game servers according to your
budget and demand. In order to do so, you do not explicitly create VMs but define parameters that determines
how they get created on your behalf. This process is called deploying or creating a build.
As part of configuration process, you would upload a game server build that would run as a containerized
application on the VMs.

What you need


Developer account on PlayFab.com
Enable PlayFab Multiplayer Servers feature
Your server-client game source code
If you don't have a server-client game yet, use our samples to see how it works instead. One of the samples is a
wrapper application that enables you to wrap an existing game server so that it would work on PlayFab
Multiplayer Servers. To learn more, see Create your first server.
If you're unsure of the terms used here, see Server terms.

1. Author a game server build


A game server build typically contains game assets and an executable you want running on the servers/virtual
machines (VMs).
When using PlayFab Multiplayer Servers, you have to integrate the PlayFab Game Server SDK (GSDK) into your
usual game server build. This integrated game server build is known as the PlayFab Multiplayer Game Server
Build.
For detailed integration steps, see Author a game server build. To learn more about the internal structure, see
Server terminology and Game server basics.

2. Deploy a build
Once you have a game server build that can run on PlayFab Multiplayer Game Servers as described in the step
above, you can move into configuring how you want the servers/virtual machines (VMs) to be created for you.
This step is known as creating or deploying builds.
You can specify the type of servers you want, regions they are in, what is on the server, and how they scale.
For details, see Deploy a build.

3. Scale game servers


After creating builds, the service is able to dynamically spin up new virtual machines and recycle used ones. This
would ensure that your title is able to fulfill player demand and maintain standby levels that you've specified. To
learn more about configuring this scaling behavior, see Scaling Standby, Scheduled Standby, and Dynamic
Standby.
Now, you can also manage scaling using APIs. To learn more, see Scaling Programatically.

4. Measure player latency to Azure regions


When players initiate a multiplayer experience, you should send User Datagram Protocol (UDP) messages to our
Quality of Service (QoS) beacons. Based on the time between sending the UDP message and receiving a
response, you can measure the network latency. The latency measurements can be used to determine the
datacenters in which to request a game server for the best experience.
To learn more and see sample code, see Using QoS beacons to measure Player latency to Azure.

5. Request game servers


When a player needs multiplayer servers, it can allocated from the build's standby pool. This request can come
from many sources, including PlayFab Matchmaking, a lobby or matchmaking service you operate, directly from
a client calling PlayFab, and more.
PlayFab Matchmaking service is a cross-platform matchmaking service that is able to automatically allocate
PlayFab Multiplayer Servers. For more information how to activate server allocation, see Integrating
matchmaking with PlayFab Multiplayer Servers.

6. Connect and play


PlayFab will fulfill a server request within one second if standby servers are available. Once a server has been
put into the active state, clients can connect to the server and play.
Image below illustrates how PlayFab Multiplayer Servers hosting works, incorporating the steps above.

See also
Create your first server
Scaling game servers
Pricing
Terminology
Resources and samples
Enable PlayFab Multiplayer Server feature
5/24/2022 • 2 minutes to read • Edit Online

PlayFab Multiplayer Server is not automatically enabled when you sign up for a PlayFab account. In order to use
and view the servers, you need to enable the feature from Game Manager or use API/PowerShell.
You have to enable the feature using Game Manager if you do not yet have a payment method on the account.
Certain servers have limited free usage and capacity limits. They can be used during evaluation and
development. If you are enrolled in paid pricing plans, you may request for additional server cores. To learn
more, see Managing Server cores quota.

Enable using Game Manager


1. Log into your developer account on PlayFab.com
2. Go to My Studios and Titles page and select your game title to display the dashboard. If you have not
created one, you have to create a new title.
3. Go to Multiplayer > Ser vers page
4. Select Enable
In order to complete the process, you need to have a payment form associated with the account. Follow the
instructions on screen to add this information.

See also
Create your first server
Author a game server build
Deploy a build
Using PlayFab Multiplayer Servers to host multiplayer games
Create VMs
5/24/2022 • 2 minutes to read • Edit Online

This topic outlines the process to start deploying virtual machines (VMs) for your game servers.
Using our service, you configure VMs to be automatically spun up globally as game servers according to your
budget and demand. In order to do so, you do not explicitly create VMs but define parameters that determine
how they get created on your behalf. This process is called deploying or creating a build for the VMs.
For general steps to deploy a build, see the section below. If you already have a build and want to update it, see
Safe deployment using alias.

NOTE
The builds that you deploy for VMs are not game server builds. This build defines when and how VMs are deployed.
Game server builds run on servers, just like client builds run on clients. You upload the game server build as an asset or
include it as part of a container image, so it runs on the VMs when it gets created.

Steps
Details about each available option are provided in Build definition and configuration.
1. Select from a broad range of VMs distributed globally based on number of cores, storage space, and RAM.
For more information about the VMs, see Multiplayer Servers details and price
2. Select the OS for the VM—Windows or Linux. The way builds are deployed for Linux servers are similar to
Windows servers with a few important differences. To learn more, see Using Windows and Linux servers.
3. Upload your assets like the PlayFab Multiplayer Game Server Build. For more information on how to create
this, see Author a game server build.
4. Determine network settings—port number and protocol
5. Set other parameters such as maximum number of servers and number of standby servers for the regions
Once you've provided a valid build definition, the build starts deploying. You will be automatically directed to the
Ser ver page. In 5-10 minutes, you will see standby machines for your build, as shown below.

Ways to deploy
There are two ways to deploy or create a build for the VMs.
1. PlayFab portal—Game Manager
2. Using PowerShell/API
To help you evaluate and develop using our servers, certain servers have limited free usage and capacity limits.
For more information, see What comes with your basic PlayFab Core Services package?.
To start deploying a build using our samples, see Create your first server.

TIP
When you're not using the servers during development, remember to turn them off. Servers in all states, including
standby, are counted against your free allotment. You can set standby servers to zero using Game Manager under Region
settings. Alternatively, use the PowerShell/APImethod to set Regions.StandbySer ver=0 . You can also delete the build to
ensure all servers are turned off in Game Manager.

See also
Create your first server
Deploy a build using Game Manager
Deploy a build using PowerShell/API
Create your first server
5/24/2022 • 2 minutes to read • Edit Online

This topic describes how you can use our samples to create your first game server using PlayFab Multiplayer
Servers. We recommend using the wrapper sample to help you create your first server.
In order to use and view the servers, you need to enable the Servers feature from Game Manager. For
instructions, see Enable the PlayFab Server feature.

What you will learn


1. Deploy game servers using PlayFab Multiplayer Servers
2. Create builds that can be used to deploy game servers/VMs using Game Manager or PowerShell via APIs
3. Scale game by defining standby, maximum servers

TIP
Certain servers have limited free usage and capacity limits. You can use them during evaluation and development. If you
are enrolled in paid pricing plans, you may request additional server cores. To learn more, see Managing Server cores
quota. It is also possible to use to test the set up and integration locally using LocalMultiplayerAgent.

Wrapper sample
The Wrapper sample, also known as wrappingGsdk, wraps an existing game so it can be used in the deployment
of builds for game servers that use Windows OS or Linux OS .
Instead of integrating your game server build with GSDK, it uses a wrapper as a workaround by processing the
standard output and error streams to call GSDK methods. Basically, the wrapper application converts your
typical game server build into one that can be used with PlayFab Multiplayer Servers.

IMPORTANT
A wrapper is a workaround by processing the standard output and error streams to call GSDK methods and it's not
meant for production use. There is additional info about GSDK integration in the sample, see Program.cs. For more
information, see Author a game server build.

To deploy servers using a wrapper, see:


1. Use Wrapper on Fakegame
2. Use Wrapper with your existing game server

Next steps
PlayFab Multiplayer Server API Reference
PlayFab Multiplayer Server resources and samples
PlayFab Multiplayer Server SDKs
Build definition and configuration
5/24/2022 • 3 minutes to read • Edit Online

This topic describes the parameters you need to specify when deploying/creating a Virtual Machine (VM)/game
server build.
A build is created by specifying its build definition and build configuration.
Build definition cannot be modified after it is created. This requires you to select what Virtual Machines (VMs)
you want, upload your PlayFab Multiplayer Game Server Build, assets, certificates, and more.
Build configuration determines how your game scales across Azure. This can be modified at any time in a
build's life.
You can also view the VM build definition and configuration on the New Build page in Game Manager. For
instructions, see How to view the New Build page using Game Manager.
Build definition
Build definition is determined by the following list of parameters.
For sample values you can use to deploy a simple server, see Walk-through of deploying builds using Game
Manager.

PA RA M ET ER DESC RIP T IO N USA GE

Build Name This is a string used to refer to the Easy identifier for the different builds
build. that you maintain

Virtual machine (VM) selection A drop-down list of global distributed Select the VMs based on what you
Azure VMs with different technical need—number of cores, RAM, storage,
specifications region. For details, see Multiplayer
Servers details and price sheet.

Servers per machine Number of game servers hosted on


each VM. The number of cores in the
VM is split by the number of servers.

Virtual machine OS Select Windows or Linux platform.

Container The container that will host your game For Windows, you can simply select
server. the managed Windows Server Core
containers. For Linux-based VMs, see
Deploying Linux-based builds.
PA RA M ET ER DESC RIP T IO N USA GE

Assets Files you want uploaded on the Asset filenames can only contain
servers. You can upload multiple assets alphanumeric characters, underscores,
but one of the assets must contain hyphens, and periods. You can use
your PlayFab Multiplayer Game Server C:\Assets as the typical mount path.
Build. What this means that PlayFab will
All assets combined should be less unzip your assets and mount it in the
than 10GB in size and must be in zip, container file-system (not the VM)
tar.gz or tar file type. as a folder in the C drive under Assets.
Each asset has a mount path
associated with it. This specifies where
it is mounted in the container file
system.

Start command The command to run when the game


server starts, make sure to include any
arguments that you need.

Network Define the port name, number, and


protocol (TCP or UDP) to be used for
incoming network traffic. Outgoing (or
solicited) network flows do not need to
be configured. For more networking
information, see Connecting clients to
game servers.

Certificate (optional) Upload certificates for the game server. Typically, the certificate for service-to-
This is a .pfx (Windows) or .pem (Linux) service authentication is installed
file containing the certificate to be through this configuration.
installed within the container.
Certificate names can only contain
letters and numbers. No spaces or
special characters such as dashes and
underscores.

Metadata (optional) A set of property-values that can be


retrieved using GSDK

Build configuration
Build configuration is determined by the following list of parameters. When selecting the virtual machine size
and regional configuration, keep in mind the overall usage limits configured for your PlayFab title. For more
information, see Accessing increased core limits and additional Azure regions.

PA RA M ET ER DESC RIP T IO N

Region Select the Azure region where game servers should be


deployed. Define the number of standby servers and
maximum servers.

Standby servers How many game servers should be maintained in a "standby


state" to handle incoming allocations in the specified region.
This should be determined by the maximum allocation rate
(allocations per second) for the build, and tuned over time as
player behavior changes.

Maximum servers The maximum number of game servers to operate in the


specified region
How to view the New Build page using Game Manager
This is the fastest way to view what's required when deploying/creating a VM build.
Log into your developer account on PlayFab.com
Go to My Studios and Titles page and select your game title to display the dashboard
Go to Multiplayer > Ser vers page, select New Build at the top right to create a new build

NOTE
The Multiplayer Servers feature needs to be enabled in order to access and view the page. If you haven't done so, see
Enable PlayFab Multiplayer Server functionality

Next step
Create your first server
Walk-through of deploying builds using Game Manager
Using PlayFab Multiplayer Servers to host multiplayer games
Pricing
Terminology
Resources and samples
Builds overview page
5/24/2022 • 2 minutes to read • Edit Online

This article describes the Builds overview page for Multiplayer Servers in Game Manager.
From the Builds page, you can view summary information and edit shared settings for your servers. This
includes:
A broad overview of your build settings and their overrides
Access to managing components shared across builds such as assets and aliases
View complimentary services available to the build.

Build aliases
To access your aliases, select Manage on the Aliases card at the top of the Builds over view page. The manage
aliases page allows you to:
Create new build aliases
View details of aliases
Edit and delete aliases

Title assets
To access assets select on the Manage button on the Assets card to navigate to the Manage Assets page.
The Manage Assets page allows you to view and manage your title's assets. This includes:
Uploading new assets
Viewiewing assets associated with a build
Viewiewing assets unassociated with a build Both assets associated and unassociated with a build may be
downloaded to a local disk. Only assets unassociated with a build can be selected for deletion.

Services summary
Under the Ser vices summar y you can view your current cost, amount of free compute hour remaining, and
free network egress you have left for the month. For more information on billing, select the “View billing
summary” on the page. For an expanded view, select "More details".

See also
Servers Overview
VM performance metrics
Servers overview page
5/24/2022 • 2 minutes to read • Edit Online

This article describes the servers page for a specific build for Multiplayer Servers in Game Manager.
To get to this page, you'll need to select a build from the builds overview page and then select the Servers tab at
the top.
From the Servers page, you can see details of your Virtual Machines (VMs). This page will list all the VMs and
their servers. You can search for a specific server, filter, or request a server. Once you expand a VM, the following
information is available per server:
Session ID (only if currently active)
Host ID
Session state
Number of players connected
Latest Activity
To find more servers you can change the Region filter at the top of the page, search for a server, or sort based
on the filters next to Display . If you would like to request a server, you can select the Request ser ver button
located on the top right portion of the page.

For VM or Host ID, only the last seven characters of the ID are shown. To view the full VM or Host ID, hover over
the ID. If you would like to copy an ID select the ID itself, a checkmark will appear next to the ID when complete.
Search servers
When searching for servers, you can search based on any of the following criteria:
VM ID
Server Host ID
Server Session ID
Server IPv4/IPv6 Address
Server FQDN
Connected players
All search results will be sorted by the latest activity column.

Server details
Once a server becomes active, you can select on the Session ID to navigate to the Ser ver Details page.
On the servers details page, you can see more information about that specific server. Including but not limited to
connected players and region. You can also shut down your server or connect to the VM by selecting the buttons
in the top-right corner.
Archived servers
Once a server has been shut down, the state will be terminated and be moved to the Archived ser vers page. If
you would like to see an archived server, select the link at the bottom of the servers page called Archived
Ser vers . The list of archived servers will show you the last 30 days of servers that have been archived.

Server logs
If you find that you would like to learn more about your archived servers, you can download the logs found
under Archived Ser vers . Next to each server is a Download logs button if you select that it will download a
zip file of your logs from that file.
See also
Archiving and retrieving multiplayer server logs
Builds overview
Basics of a PlayFab game server
5/24/2022 • 3 minutes to read • Edit Online

PlayFab operates game servers as containerized applications. This tutorial describes how game servers are
packaged and integrated with PlayFab systems.

Containerizing and packaging game servers


Windows
On Windows, typically you package the game server executable and other files as zip files, and upload them as
game assets. Assets are combined with a container image to create your game server build. The base container
image provides the Windows operating system files, and the execution environment that allows the game to
run. PlayFab provides a set of managed container images to use for Windows builds. When a Windows build is
created through Game Manager or APIs like CreateBuildWithManagedContainer(), you specify the assets and
where they should be mounted within the container's file system. You also specify the shell command to start
the game ( StartGameCommand ), this might be similar to what is shown below.

C:\GameCoreApp\GameServer.exe -mode RETAIL

The StartGameCommand must start an application that uses the PlayFab Game Server SDK, to call ReadyForPlayers
when ready to serve game clients. The container will be terminated and recycled when the application process
exits.
Linux
On Linux, you create the container image yourself by packaging game executable and assets. Usage of assets
that are combined with the container image at runtime is optional. When a Linux build is created through Game
Manager or APIs like CreateBuildWithCustomContainer(), you can optionally specify the assets and where they
should be mounted within the container's file system. Specification of the shell command to start the game (
StartGameCommand ) is also optional, since this command can also be included in the container image.

NOTE
Check this page for more information regarding creating Linux container images for PlayFab Multiplayer Servers

Managed Containers for Windows


PlayFab currently supports one managed container; the PlayFab Multiplayer container image, based on
Windows Server Core. You can download this container through Docker Hub so that your local environment
matches the runtime environment in Azure.
There are debugging tools that allow you to step through the multiplayer server state machine locally on your
dev box.
For more information, check out Locally debugging game servers and integration with PlayFab.
The following image shows the key flows for uploading a game server and combining this package with a
selected container.
Managed container updates
Managed containers are the easiest integration option for Windows projects, and a good place to start if you are
unfamiliar with containers.
A key feature of managed containers is that PlayFab will automatically update the base image with critical
security fixes to ensure reliable play. Generally, security updates happen every month, and should not cause
service interruption. To learn more, see OS patch updates for Windows.
During an upgrade, standing-by sessions that are naturally being recycled will be replaced with an updated
container image and the same game server package.
When PlayFab intends to update a managed container image that you are using, you will receive PlayStream
events.

Integrating the PlayFab Game Server SDK


Learn more at: Integrating game servers with the PlayFab Game Server SDK (GSDK)
The PlayFab Game Server SDK (GSDK) is provided in multiple programming languages, like C++ , C# and Java .
The GSDK connects your game server to a local agent installed on the VM. This agent facilitates key server
interactions with the PlayFab control infrastructure.

When your game server is initialized, it will be put into a preparing state, with PlayFab waiting for your game
server to call ReadyForPlayers() .
Once this is called, the game server is put into a standing by state, and waits for allocation requests from your
matchmaking service into PlayFab via the RequestMultiplayerServer method.
The image displayed below shows the States of a PlayFab multiplayer server.
Ostensibly, calling ReadyForPlayers() is the only requirement to get your game server to run and continue
running. However, there are several callbacks/events that you may want to process in order to provide the best
user experience.

Server scripts and PlayFab-configured environment variables


In some cases you may want game servers to run a CMD, PowerShell or bash script (a "bootstrapper"), which
then launches your compiled game server executable. This script may configure the container's internal
environment, pass command-line arguments to the executable, or any other task you don't want to execute in
the game server executable itself.
As a convenience, PlayFab configures some build information as the following environmental variables in the
container. These can also be accessed through the GSDK, but using the environmental variables can be easier
from a script.
PF_TITLE_ID - Title Id for the session host
PF_BUILD_ID - Build Id for the session host
PF_REGION - Azure Region for the session host
PUBLIC_IPV4_ADDRESS - Public IP Address for the VM
PF_VM_ID - Unique identifier for the VM (like 'xcloudeau4u4yyxj4xymu:AustraliaEast:1E03_6f27ad88-9bc3-
4ea3-8d16-
75480aba4637:tvmps_0e05c37e0bbdca298a09fb0d597bd666eb7c5fd0ebcf1fed4c52e608a39a7c9c_d')
CERTIFICATE_FOLDER - Folder containing game certificates
PF_SERVER_LOG_DIRECTORY - Folder containing game logs
Terminology
5/24/2022 • 2 minutes to read • Edit Online

This topic explains the terms used for PlayFab Multiplayer Server. We understand that it can be confusing since
the word server is used in multiple places.
The internal structure of the PlayFab Multiplayer Server and general relationship of the various components is
also lightly covered here. For details, see Basics of a PlayFab game server.

PlayFab Multiplayer Servers


PlayFab Multiplayer Servers can also be known as PlayFab virtual machines (VMs) and Servers.
They are Azure VMs with PlayFab managed service functionalities. Added functionalities optimize them for use
as multiplayer game servers.
Each PlayFab VM:
Has a component known as PlayFab VM agent. PlayFab VM agent provides information about your game
server's current state, health status, players that are currently connected, and other telemtry.
Can have multiple containers (game servers) running on them. Containers are a way to wrap up an
application into its own isolated package. To learn more, see What is a container?
Game server containers
Game servers run as containerized applications. This means that your game server executable runs inside a
container. It ensures portability because game servers now execute in a consistent environment from
development to production. The lightweight nature of containers also enables you to rapidly scale-up and scale-
down.
Each container:
Functions as a game server
Has a PlayFab Multiplayer Game Server Build. It is your usual game server build that is integrated with the
PlayFab Game Server SDK (GSDK). Specifically, the code for the game server executable must include the
GSDK and implement specific methods using APIs in the GSDK. This enables your game server to be
connected to the PlayFab VM agent.
Image below illustrates the various components of a PlayFab Multiplayer Server.
Definition of key terms
Game ser ver executable : This is a game server application that runs in containers of PlayFab VMs. It
may be a simple network repeater, a fully authoritative game server running physics and AI, or anything
in between. All game server executables needs to be integrated with PlayFab Game Server SDK (GSDK).
This allows your game server to be able to interact with the PlayFab Multiplayer platform service.
Game ser ver build : This is the full set of content that is uploaded onto the game server. It includes the
game server executable packaged with all the assets and certificates needed. It can be uploaded as
individual certificates, zip files, and/or a container image. If you don't need a custom container image, you
can use PlayFab managed Windows containers.
PlayFab Multiplayer Game Ser ver Build : This is the only type of game server build that can be used
in PlayFab Multiplayer Servers. It is your usual game server build (as defined above) that is integrated
with the PlayFab Game Server SDK (GSDK). Specifically, the code for the game server executable must
include the GSDK and implement specific methods using APIs in the GSDK.
Game ser ver : This is your game server executable running in a container. There may be multiple
containers (servers) running on a single virtual machine.
PlayFab VM agent : This agent is built into PlayFab VMs and facilitates key server interactions with the
PlayFab Multiplayer platform service. The GSDK in the game server executable connects your game
server to the PlayFab agent.
PlayFab Multiplayer platform ser vice : Managed service that runs in the background for PlayFab
Multiplayer Servers. It communicates information through PlayFab VM agent about your game server's
current state, health status, players that are currently connected, and other telemtry.

Next steps
Using PlayFab Multiplayer Servers to host multiplayer games
Author a game server build
Deploy a build
Author a game server build
5/24/2022 • 2 minutes to read • Edit Online

This topic explains how to create a game server build for PlayFab Multiplayer Servers (MPS). A game server
build typically contains game assets and an executable that runs on the server.
When using PlayFab Multiplayer Servers, you need to make modifications to your regular game server build so
that it can work on them. This modified server build is called a PlayFab Multiplayer Game Server Build.
If you're unsure of the terms used, see Terminology.

How to create a PlayFab Multiplayer Game Server Build


You can convert your regular game server build into a PlayFab Multiplayer Game Server Build by integrating it
with the PlayFab Game Server SDK (GSDK).
1. Download the GSDK you need
2. Open your existing game server code project and add the GSDK as a dependency
3. Implement essential functions (at minimum the Star t and ReadyForPlayers methods) using the APIs in the
GSDK. For code snippets, see Integrating game servers with GSDK.
4. Build and compile the game server executable to create the PlayFab Multiplayer Game Server Build
This new build now helps manage game servers that are created using PlayFab Multiplayer Servers. Adding
more methods provide greater control and gives you information about the servers. For more instructions, see
the Program.cs in the Wrapper sample.

NOTE
Consider using our open source debugging utility LocalMultiplayerAgent to test your game server before uploading it
into MPS. This will help prevent unnecessary costs in case your game server fails to start or is not properly integrated
with GSDK. You can download LocalMultiplayerAgent here and check the instructions here. LocalMultiplayerAgent can
also be used for iterative testing/debugging during the development of your game server.

Next step
When using Windows game servers, you have to use the managed Windows container image. So the PlayFab
Multiplayer Game Server Build can be uploaded as a zipped file combined with other dependencies (DLL files)
during the Deploy a build process. To help you determine what needs to be included in the zipped file, see
Determining required DLLs.
When using Linux game servers, you need to Create your custom Linux container image and the PlayFab
Multiplayer Game Server Build can be included as part of the image. Once your custom image is uploaded, you
would be able to Deploy a build.

See also
Determine DLL files to be included in the asset package for Windows servers
Local debugging and integration for Windows servers
Create Linux servers
Integrating game servers with the PlayFab Game
Server SDK (GSDK)
5/24/2022 • 9 minutes to read • Edit Online

Overview
The PlayFab Game Server SDK (GSDK) is provided in C++, C#, and Java versions. The GSDK connects your game
server to the PlayFab agent installed on the VM. This agent facilitates key server interactions with the PlayFab
Multiplayer platform.

Basic integration
For your game server to be able to communicate with the PlayFab multiplayer platform, you need to integrate
with the GSDK. At a minimum, you must implement the Start and ReadyForPlayers methods in your game
server.

int main()
{
// Call this while your game is initializing; it will start sending a heartbeat to our agent and put the
game server in an Initializing state
Microsoft::Azure::Gaming::GSDK::start();

/* Add any other initialization code your game server needs before players can connect */

// Call this when your game is done initializing and players can connect
// Note: This is a blocking call, and will return when this game server is either allocated or
terminated
if (Microsoft::Azure::Gaming::GSDK::readyForPlayers())
{
// readyForPlayers returns true when an allocation call has been done, a player is about to connect!
}
else
{
// readyForPlayers returns false when the server is being terminated
}

}
static void Main(string[] args)
{
// Call this while your game is initializing; it will start sending a heartbeat to our agent and put the
game server in an Initializing state
GameserverSDK.Start();

/* Add any other initializion code your game server needs before players can connect */

// Call this when your game is done initializing and players can connect
// Note: This is a blocking call, and will return when this game server is either allocated or
terminated
if (GameserverSDK.ReadyForPlayers())
{
// readyForPlayers returns true when an allocation call has been done, a player is about to connect!
}
else
{
// readyForPlayers returns false when the server is being terminated
}

public static void main(String[] args)


{
// Call this while your game is initializing; it will start sending a heartbeat to our agent and put the
game server in an Initializing state
GameserverSDK.start();

/* Add any other initializion code your game server needs before players can connect */

// Call this when your game is done initializing and players can connect
// Note: This is a blocking call, and will return when this game server is either allocated or
terminated
if (GameserverSDK.readyForPlayers())
{
// readyForPlayers returns true when an allocation call has been done, a player is about to connect!
}
else
{
// readyForPlayers returns false when the server is being terminated
}

Logging with the GSDK


When your game server ends, the PlayFab VM agent will zip any log files, and make them available to you.
There are two ways to add log files from your game:
1. Use the GSDK's Log method - It will add your own log lines to the GSDK log file.
2. Write your own log file in the appropriate log directory that the PlayFab VM agent will zip up and upload.

// This will add your log line to the GSDK log file, alongside other information logged by the GSDK
Microsoft::Azure::Gaming::GSDK::logMessage("Here is a sample log");

// Alternatively, you can log your own files to the log directory
std::string logFolder = Microsoft::Azure::Gaming::GSDK::getLogsDirectory();
// This will add your log line to the GSDK log file, alongside other information logged by the GSDK
GameserverSDK.LogMessage("Here is a sample log");

// Alternatively, you can log your own files to the log directory
string logFolder = GameserverSDK.GetLogsDirectory();

// This will add your log line to the GSDK log file, alongside other information logged by the GSDK
GameserverSDK.log("Here is a sample log");

// Alternatively, you can log your own files to the log directory
String logFolder = GameserverSDK.getLogsDirectory();

Gracefully shutting down your game server


There are three scenarios in which your game server will end:
1. Your game server application exits.
2. PlayFab terminates your game server because there are more game servers available than is necessary
for the current player load.

NOTE
PlayFab will only terminate game servers that are not currently active.

3. Azure will perform required maintenance on the virtual machine that is hosting your game server.
For (1) above: You control when it happens, and can perform any necessary cleanup before your application
exits.
For (2) and (3) above: The GSDK provides a way for you to know when they will occur, by specifying a callback
method.
// This method will be called in case #2, when PlayFab terminates the game server
void onShutdown()
{
printf("GSDK is shutting me down!!!\n");
/* Perform any necessary cleanup and end the program */
std::exit(0);
}

// This method will be called in case #3, when Azure will perform maintenance on the virtual machine
void onMaintenanceScheduled(tm t)
{
#ifdef WINDOWS
time_t local = _mkgmtime(&t);
double delta = difftime(local, time(NULL));
struct tm buf;
char str[26];
gmtime_s(&buf, &local);
asctime_s(str, sizeof str, &buf);
printf("UTC: %s", str);
localtime_s(&buf, &local);
asctime_s(str, sizeof str, &buf);
printf("local: %s", str);
printf("delta: %f", delta);
#else // Linux
time_t local = timegm(&t);
double delta = difftime(local, time(NULL));
printf("UTC: %s\n", asctime(gmtime(&local)));
printf("local: %s\n", asctime(localtime(&local)));
printf("delta: %f\n", delta);
#endif

/* Perform any necessary cleanup, notify your players, etc. */


}

int main()
{
Microsoft::Azure::Gaming::GSDK::start();
Microsoft::Azure::Gaming::GSDK::registerShutdownCallback(&onShutdown);
Microsoft::Azure::Gaming::GSDK::registerMaintenanceCallback(&onMaintenanceScheduled);

// Continue initializing your game


}

// This method will be called in case #2, when PlayFab terminates the game server
static void OnShutdown()
{
GameserverSDK.LogMessage("Shutting down...");
/* Perform any necessary cleanup and end the program */
}

// This method will be called in case #3, when Azure will perform maintenance on the virtual machine
static void OnMaintenanceScheduled(DateTimeOffset time)
{
/* Perform any necessary cleanup, notify your players, etc. */
}

static void Main(string[] args)


{
GameserverSDK.Start();
GameserverSDK.RegisterShutdownCallback(OnShutdown);
GameserverSDK.RegisterMaintenanceCallback(OnMaintenanceScheduled);

// Continue initializing your game


}
// This method will be called in case #2, when PlayFab terminates the game server
private static void onShutdown()
{
System.out.println("Shutting down...");
/* Perform any necessary cleanup and end the program */
}

// This method will be called in case #3, when Azure will perform maintenance on the virtual machine
private static void onMaintenanceScheduled(ZonedDateTime time)
{
/* Perform any necessary cleanup, notify your players, etc. */
}

static void Main(string[] args)


{
GameserverSDK.start();
GameserverSDK.registerShutdownCallback(Main::onShutdown);
GameserverSDK.registerMaintenanceCallback(Main::onMaintenanceScheduled);

// Continue initializing your game


}

Giving PlayFab information about your game server


Currently there are two things you can communicate to PlayFab using the GSDK:
1. Your game server's current health status.
2. A list of players that are currently connected to your game server.
These two pieces of information will be transmitted to PlayFab in the next heartbeat, and can currently be used
for reporting.

static std::vector<Microsoft::Azure::Gaming::ConnectedPlayer> players;

void playerConnected()
{
// When a new player connects, you can let PlayFab know by adding it to the vector of players and
calling updateConnectedPlayers
players.push_back(Microsoft::Azure::Gaming::ConnectedPlayer("player_tag"));
Microsoft::Azure::Gaming::GSDK::updateConnectedPlayers(players);
}

// This method will be called on every heartbeat to check if your game is healthy, as such, it should return
very quickly
bool isHealthy()
{
// Return whether your game server should be considered healthy
return true;
}

int main()
{
Microsoft::Azure::Gaming::GSDK::start();
Microsoft::Azure::Gaming::GSDK::registerHealthCallback(&isHealthy);

// Continue initializing your game


}
static private List<ConnectedPlayer> players = new List<ConnectedPlayer>();

static void OnPlayerConnected()


{
// When a new player connects, you can let PlayFab know by adding it to the vector of players and
calling updateConnectedPlayers
players.Add(new ConnectedPlayer("player_tag"));
GameserverSDK.UpdateConnectedPlayers(players);
}

// This method will be called on every heartbeat to check if your game is healthy, as such, it should return
very quickly
static bool IsHealthy()
{
// Return whether your game server should be considered healthy
return true;
}

static void Main(string[] args)


{
GameserverSDK.Start();
GameserverSDK.RegisterHealthCallback(IsHealthy);

// Continue initializing your game


}

private static ArrayList<ConnectedPlayer> players = new ArrayList<ConnectedPlayer>();

private static void onPlayerConnected()


{
// When a new player connects, you can let PlayFab know by adding it to the vector of players and
calling updateConnectedPlayers
players.add(new ConnectedPlayer("player_tag"));
GameserverSDK.updateConnectedPlayers(players);
}

// This method will be called on every heartbeat to check if your game is healthy, as such, it should return
very quickly
private static GameHostHealth getGameHealth()
{
// Return whether your game server should be considered healthy
return GameHostHealth.Healthy;
}

static void Main(string[] args)


{
GameserverSDK.start();
GameserverSDK.registerHealthCallback(Main::getGameHealth);

// Continue initializing your game


}

Getting configuration settings within your game server


There are several PlayFab settings related to your game server that you can retrieve using the GSDK.

NOTE
Two of these settings are actually passed in to PlayFab by your clients, as part of the call to request a multiplayer server.
So those settings will not be available to your game server until it is allocated.
// Get all the configuration values
std::unordered_map<std::string, std::string> config = Microsoft::Azure::Gaming::GSDK::getConfigSettings();

// Retrieve a particular configuration value


auto it = config.find(Microsoft::Azure::Gaming::GSDK::SESSION_COOKIE_KEY);

if (it != config.end())
{
std::string sessionCookie = config[Microsoft::Azure::Gaming::GSDK::SESSION_COOKIE_KEY];
}

// Here some other useful configuration keys (the full list is in gsdk.h)
static constexpr const char* SERVER_ID_KEY; // ID given to your game server upon creation
static constexpr const char* LOG_FOLDER_KEY; // Path to the folder that should contain all log files
static constexpr const char* CERTIFICATE_FOLDER_KEY; // Path to the folder that contains any game
certificate files
static constexpr const char* TITLE_ID_KEY; // PlayFab Title ID for this game server
static constexpr const char* BUILD_ID_KEY; // PlayFab Build ID for this game server
static constexpr const char* REGION_KEY; // Azure Region this server is running in

// These two keys are only available after allocation (once readyForPlayers returns true)
static constexpr const char* SESSION_COOKIE_KEY; // The Session Cookie you passed into the allocation call
when you requested a server
static constexpr const char* SESSION_ID_KEY; // The Session ID you specified in the allocation call when you
requested a server

// Get all the configuration values


IDictionary<string, string> config = GameserverSDK.getConfigSettings();

// Retrieve a particular configuration value


if (config.TryGetValue(GameserverSDK.SessionCookieKey, out string sessionCookie))
{
// sessionCookie contains the value
}

// Here are some other useful configuration keys (the full list is in the GameserverSDK class)
public static string ServerIdKey; // ID given to your game server upon creation
public static string LogFolderKey; // Path to the folder that should contain all log files
public static string CertificateFolderKey; // Path to the folder that contains any game certificate files
public static string TitleIdKey; // PlayFab Title ID for this game server
public static string BuildIdKey; // PlayFab Build ID for this game server
public static string RegionKey; // Azure Region this server is running in

// These two keys are only available after allocation (once readyForPlayers returns true)
public static string SessionCookieKey; // The Session Cookie you passed into the allocation call when you
requested a server
public static string SessionIdKey; // The Session ID you specified in the allocation call when you requested
a server
// Get all the configuration values
Map<String, String> config = GameserverSDK.getConfigSettings();

// Retrieve a particular configuration value


if (config.containsKey(GameserverSDK.SESSION_COOKIE_KEY))
{
String sessionCookie = config.get(GameserverSDK.SESSION_COOKIE_KEY);
}

// Here are some other useful configuration keys (the full list is in the GameserverSDK class)
public static final String SERVER_ID_KEY; // ID given to your game server upon creation
public static final String LOG_FOLDER_KEY; // Path to the folder that should contain all log files
public static final String CERTIFICATE_FOLDER_KEY; // Path to the folder that contains any game certificate
files
public static final String TITLE_ID_KEY; // PlayFab Title ID for this game server
public static final String BUILD_ID_KEY; // PlayFab Build ID for this game server
public static final String REGION_KEY; // Azure Region this server is running in

// These two keys are only available after allocation (once readyForPlayers returns true)
public static final String SESSION_COOKIE_KEY; // The Session Cookie you passed into the allocation call
when you requested a server
public static final String SESSION_ID_KEY; // The Session ID you specified in the allocation call when you
requested a server
Determining required DLLs that need to be
included in the asset package
5/24/2022 • 2 minutes to read • Edit Online

This article helps you generate a list of DLLs required to run your Windows game server in PlayFab Multiplayer
Servers. By default, the managed container image includes many commonly used DLLs. To determine which
additional DLLs are needed, compare the list of DLLs for your game server with the list of DLLs included in the
manged container image. Any additional DLLs must be included in your asset zip file.

Determine required DLLs


Use the ListDlls utility to list all of the DLLs that are loaded when you run your game server locally. To generate
the list:
1. Download ListDlls from sysinternals.
2. Run your game server executable on your local machine by using the instructions found in local debug steps
in process mode or as a standalone process without using the LocalMultiplayerAgent.
3. Run listdlls and specify your running game server as a parameter. Example:
listdlls ServerLoadSimulator.exe
4. Compare the list that is output against the list of DLLs included in your asset zip file (typically everything in
the same folder as your executable). The delta between the lists are the system DLLs that are required by
your game server.

Compare required DLLs with those included in container


With the list of system DLLs determined, the next step is to determine which of these system DLLs are already
included in the container.
1. Download the PlayFab multiplayer container image. To download the container image, run the setup.ps1
script referenced in local debug steps. Alternatively, allocate a new MPS instance and connect via Remote
Desktop. All Windows MPS instances will have the container image downloaded.
2. Start a command line session in a new docker container by running the following command. You might need
to run an administrator command window.
docker run -it mcr.microsoft.com/playfab/multiplayer:wsc-10.0.17134.950 cmd

Replace "wsc-10.0.17134.950" with the tag of the docker image you downloaded in step 1. If you are not sure of
the correct tag, run docker images to list the downloaded images.

1. From the command line, locate the folders that correspond to the folders of the required DLLs on your local
machine. List the DLLs present in the container and compare to the list of required DLLs that you generated.
Any DLLs in the required list, but not present in the container, must be included in your asset zip file.
2. To end the cmd process and cause the container to stop, type exit .
Integrating the PlayFab GSDK into Unity
5/24/2022 • 2 minutes to read • Edit Online

Multiplayer Servers platform provides a GSDK library that you can integrate into your Unity game server. The
library is open source and can be found on the GSDK repository on GitHub.

Installation
You can copy the Assets/PlayFabSdk folder into your Unity project. After that, you need to enable the scripring
directive ENABLE_PLAYFABSERVER_API on your Unity Build settings (example). Alternatively, you can use the
provided Unity package file. You can find sample code in the MultiplayerServerSample project.

Usage
At a minimum, you need to implement PlayFabMultiplayerAgentAPI.Start() method and start a coroutine for
the PlayFabMultiplayerAgentAPI.ReadyForPlayers() method, like in the code below

//...
StartCoroutine(ReadyForPlayers());
//...

private IEnumerator ReadyForPlayers()


{
yield return new WaitForSeconds(.5f);
PlayFabMultiplayerAgentAPI.ReadyForPlayers();
}

You would also want to register for when the game server becomes transitions to Active using the
PlayFabMultiplayerAgentAPI.OnServerActiveCallback , like in the example below:

PlayFabMultiplayerAgentAPI.OnServerActiveCallback += OnServerActive;
// ...
private void OnServerActive()
{
Debug.Log("Server Started From Agent Activation");
// players can now connect to the server
}

NOTE
For more information regarding game server states, check Basics of a PlayFab game server section here

Moreover, you can implement the following callbacks on your game server:
PlayFabMultiplayerAgentAPI.OnMaintenanceCallback triggered when Azure needs to perform maintenance on
the VM
PlayFabMultiplayerAgentAPI.OnShutDownCallback triggered when a termination notification is received
PlayFabMultiplayerAgentAPI.OnAgentErrorCallback triggered if there's any error between game server and
PlayFab VM Agent communication
NOTE
For more GSDK samples, you can take a look at our MPS Samples repository here
Deploy builds using Game Manager
5/24/2022 • 6 minutes to read • Edit Online

This article lists the general steps to deploy/create builds for VMs using Game Manager.
If this is your first time deploying a build, we recommend deploying a build using the Windows Runner C#
sample or Wrapper sample. Both will come with all the assets you need to actually deploy servers.

NOTE
In order to use and view the PlayFab Multiplayer Servers, you need to enable the feature from Game Manager. For
instructions, see Enable the PlayFab Server feature.

For details about the values you can use for each parameter, see Build definition.

Steps to deploy through Game Manager


1. Log into your developer account on PlayFab.com. Go to My Studios and Titles page and select your game
title to display the dashboard
2. Go to Multiplayer > Ser vers page, select New Build at the top right to create a new build
3. Starting with the Build details, use a descriptive string as the Build Name
4. Select a server with limited-free usage, such as Dasv4 during development. To learn more about pricing, see
Billing for PlayFab Multiplayer Servers
5. Set a value you want for Servers per machine
Image below shows values used in the info section.

6. Next we have the server details portion where you'll need to select an OS type either Windows or Linux .
Then you'll select your server type, either process or container based on the OS you choose.

NOTE
For Linux platform, you need to create your own container image. For more instructions, see Create and deploy Linux
container images. If you've already uploaded a container image, it will appear in the Image dropdown. To use it, select the
image.

Once you have selected your OS type, you can then choose the server type. Based on the OS/Server type you'll
have the following features you can enable.
Virtual Machine Metrics Preview: By enabling this it allows you to see system level metrics such as CPU,
memory, network, etc. To learn more, read our VM performance metrics (preview) article
Windows Core Preview: Allows you to test the newest versions of Windows operating system on test builds
to see how your game will run with the newer operation system. To learn more, read OS patch level updates
for Windows
Automatic Crash Dump Collection: Allows you to enable automatic crash dump collection on your Windows
Container server types. You can choose between doing a full, mini, or custom dump. To learn more, read
Enabling automatic collection of crash dumps
Server details for Process mode
Image below shows values used in the OS section when you select Windows as the platform but use Process
based server type. There is also the option of using Linux process based servers as well.

Server details for Container mode


Image below shows values used in the OS section when you select Linux as the platform but use Container
based server type. There is also the option of using Windows container based servers as well.

Assets for builds


7. Under Assets, select Upload . Navigate to folder with the compiled PlayFab Multiplayer Server Build and then
select the .zip package to upload.
Assets for Windows servers
For Windows platform, you must upload a PlayFab Game Server Build as an asset. To learn how to create a
PlayFab Game Server Build, see Author a game server build. Upload assets to modify and customize the
Windows container image. Mount path for the assets in windows servers should be rooted in C drive.
Assets for Windows container ser vers
Assets for windows servers will need to be in the C drive otherwise the API may return an error. The mount path
is only necessary for containers.

NOTE
Do not provide a mount path for process based servers.

Assets for Linux servers


For Linux platform, uploading an asset is optional as the Game Server can be included as part of the
container image. But you must still have a Game Server, make sure the mount path is valid within the
container you're uploading.
If you're uploading assets:
Set C:\Assets or select a different path as the mount path
Set C:\Assets\YourGameSer verBuild.exe as the Start Command

Network settings
8. For network, set the port number, name, and protocol.
Setting port for container server types
If you're using a container server type, you should specify the port number.
For example, in Game Manager for a container server type, you could specify:
Port name: "gameServerPort"
Port number: 7777
Protocol: UDP
Then in your code you would do something like this

int port = 7777; // since you already know the port


GameServer gs = new GameServer(port);
gs.start();

NOTE
In container mode, each game server runs on its own network namespace. This is the reason why every game server can
listen to the same port. The container port is dynamically mapped to a unique port on the virtual machine. However, on
process mode, all game servers run on the same network namespace. Having all game servers listen to the same port
would create conflicts, so this is why you'll need to get the ServerListeningPort from the GSDK.

Setting port for process server types


For process server type, you should use the GSDK to retrieve your port number. Don't include a port number as
part of the build definition.

Then in your code you would do something like:

var gsc = GameServerSDK.GetConnectionInfo();

var gp = gsc.Where(x=>x.Name=="gameServerPort").Single();

GameServer gs = new GameServerPort(gp.ServerListeningPort);

To view the full sample code, go to GameServerConnectionInfo.cs in GSDK/CSharp/GSDK_CSharp_Standard The


above code sample that gets the port from the GSDK would work in container mode as well.

Start command
Start command for container based servers
Your start command should be the absolute path (including the mount path) to your game executable that
should include any required arguments. For example, your start command could look like C:\Assets\wrapper.exe
-g C:\Assets\fakegame.exe arg1 arg2. Adding in the "C:\Assets" portion to your absolute path for your start
command is only required if it's a Windows container based server. This is because that's the directory where
your game asset would be extracted from.
Start command for windows process based servers
Your start command is the relative path within the uploaded asset. If the executable is directly within the asset
folder, then you can just use <yourGameServerBuild.exe>. If it is within another folder (for example
GameDirectory), then the start command would be gameDirectory/YourGameServerBuild.exe.
9. Under Regions, select the region you want to deploy the servers. Then specify the number of standby and
maximum servers.
10. Select Save to start the deployment process. You'll be taken to the build home page. The build will display
the Deploying status as show in the image below.
In a couple minutes, your build should be in the Deployed state. This means that servers are deployed and can
be allocated. For more information on allocating game servers, you can check here whereas you can use the
MpsAllocatorSample to experiment with server allocation.

Configure region information


After deploying builds, you can still modify the following parameters.
Regions
Standby servers
Maximum servers
To configure regional settings:
Go to the Ser vers > Builds page
Select the build you want to modify
On the Regions tab and go to the Ser vers by region section
Add/remove region and modify the server numbers

See also
Walkthrough: Deploy builds using Game Manager
Deploy a build using PowerShell/API
Create your first server
Wrapper C# sample
MPS Allocator Sample
Samples and resources
Deploy builds using PowerShell/API
5/24/2022 • 5 minutes to read • Edit Online

This topic provides an overview on how to deploy/create builds for VMs using Windows OS in PowerShell on a
Windows 10 development device.
When deploying a build using PowerShell/API, you are likely to be using a combination of using Game Manager
and the APIs. Hence, the PowerShell/API commands are listed by functionality below.
If this is your first time deploying a build, we recommend deploying a build using the Wrapper sample because
it comes with all the assets you need to actually deploy servers.

NOTE
In order to use and view the PlayFab Multiplayer Servers, you need to enable the feature. If you are a new user, we
recommend that you use the Game Manager method to enable this feature. For instructions, see Enable the PlayFab
Server feature.

Get your title ID and developer secret key


Get your PlayFab title ID
Log into your developer account on PlayFab.com
In Game Manager, go to My Studios and Titles page. Look for your game title and get the PlayFab
game title ID
Get the developer secret key for the title
In Game Manager, select your title > settings (gear icon)
Select Title settings , then select the Secret Keys tab to get the developer secret key
For more information about secret keys, see Secret key management.

Install the PlayFab MultiplayerAPI PowerShell module


1. Open Windows Powershell as an Administrator
2. If you have previously installed PlayFab Multiplayer Powershell module, uninstall it with following
command. This module is now deprecated.

Uninstall-Package PlayFabMultiplayer

To help you transition to the new module, see Mapping commands to find the new equivalent commands. Note
that both the commands and arguments could be different.
3. Install the new PlayFabMultiplayer API module
For detailed documentation about each command, see Cmdlet documentation.

Install-Module -Name PlayFabMultiplayerApi


TIP
Before installing the module, you may need to set your execution policy by running
Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope CurrentUser in PowerShell first. To learn more, see
PowerShell execution policies.

4. Learn more about the cmdlets in the PlayFab Multiplayer PowerShell module by running the following
command. Or you can refer to the PlayFabMultiplayerApi cmdlet reference documentation.

Get-Command -Module PlayFabMultiplayerApi | Get-Help

Obtain an EntityToken for your title


Run the following command using your title ID and associated developer key. You must run this command at the
start of any session when using the PlayFabMultiplayerApi PowerShell module.
It calls the GetEntityToken API to obtain an EntityToken and stores it in an environment variable for use in future
cmdlets.

Set-PfTitle -TitleID "mytitleID" -SecretKey "mysecretkey"

Enable multiplayer servers feature for your title


Run this cmdlet below to enable the Multiplayer Servers features. It calls the enable multiplayer servers API.

Enable-PfMultiplayerServer

If you receive an error that says


Title must have a valid payment instrument associated with it in order to enable Multiplayer Servers , see
Enable PlayFab Multiplayer Servers using Game Manager to add your payment information.

Upload an asset
Uploading an asset is mandatory when you are deploying a build for Windows servers. This is because your
assets customizes the managed Windows container image.
However, it is optional when deploying a build for Linux servers since you are able to customize the Linux
container image. To learn more, see Create Linux container images.
Run this command to upload an asset.

New-PfAsset -FilePath C:\MyAsset.zip -AssetName MyAsset.zip

where:
Filepath : Path to the local file you want to upload
AssetName : Name of the asset to upload
For more details, see New-PfAsset reference documentation.

Create a build
When creating a build for Windows servers, you need to have uploaded an asset. If not, see Upload an asset.
When creating a build for Linux servers, you need to have uploaded your custom Linux container image to
your PlayFab container registry. To learn more, see Deploying Linux servers.

IMPORTANT
Make sure you use the correct values for $vmSize and $regions if you plan to take advantage of resources offered for
free evaluation.

Sample code below to help deploy builds for Windows game servers.

$vmSize = "Standard_D2as_v4"
$regions = @( @{ StandbyServers = 1; MaxServers = 1; Region = 'EastUS'; ScheduledStandbySettings = $NULL } )
$ports = @( @{ Name = 'tcp_port'; Num = 8080; Protocol = 'TCP' }, @{ Name = 'udp_port'; Num = 8081; Protocol
= 'UDP' } )
$gameAssets = @( @{ FileName = 'MyAsset.zip'; MountPath = 'C:\Assets' } )

$buildResponse = New-PfBuild -BuildName ExampleBuild -ContainerFlavor ManagedWindowsServerCore -


StartMultiplayerServerCommand 'C:\Assets\MyCustomServer.exe' -GameAssetReferences $gameAssets -VMSize
$vmSize -MultiplayerServerCountPerVM 1 -Ports $ports -RegionConfigurations $regions

# All PlayFabMultiplayerApi cmdlets return objects, so we can pass the returned object to ConvertTo-Json for
human readability.
$buildResponse | ConvertTo-Json -depth 5

Sample code below to help deploy builds for Linux game servers.

$vmSize = "Standard_D2as_v4"
$ports = @( @{ Name = 'tcp_port'; Num = 8080; Protocol = 'TCP' }, @{ Name = 'udp_port'; Num = 8081; Protocol
= 'UDP' } )
$regions = @( @{ 'MaxServers' = 1; 'Region' = 'AustraliaEast'; StandbyServers = 1;
'ScheduledStandbySettings' = $NULL } )
$containerImageReference = @{ ImageName = "MyLinuxContainerImage"; Tag = "0.2" }

$buildResponse = New-PfBuild -BuildName ExampleBuild -ContainerFlavor CustomLinux -ContainerImageReference


$containerImageReference -VMSize $vmSize -MultiplayerServerCountPerVM 1 -Ports $ports -RegionConfigurations
$regions

# All PlayFabMultiplayerApi cmdlets return objects, so we can pass the returned object to ConvertTo-Json for
human readability.
$buildResponse | ConvertTo-Json -depth 5

List deployed builds


To see a list of builds for your title, run the commands below.

Get-PfBuild | ConvertTo-Json -depth 5

Request a multiplayer server


After creating a build, one or more servers will be created after running your .exe file. These servers are now
"standing by".
You can see them when you list all the servers running our build using this command.

Get-PFMultiplayerServer -BuildId $buildResponse.data.BuildId -Region "EastUS"


Once we see some standby servers, let's request one for gameplay...

$sessionId = New-Guid
$serverResponse = Request-PfMultiplayerServer -BuildId $buildResponse.data.BuildId -PreferredRegions
@('EastUS') -SessionId $sessionId

The response to that call includes an IPv4 address and port number that clients can connect to. In the case of
WindowsRunnerCSharp.exe, it hosts a simple webserver so you can browse to the IPv4 address and port
number to get a response:

curl "http://$($serverResponse.data.Ipv4Address):$($serverResponse.data.Ports[0].Num)"

This is the core of PlayFab multiplayer servers: within 3 seconds of your matchmaking service calling
RequestMultiplayerServer, PlayFab will allocate a new server.
These servers come from continuously refilled, standing-by server pools you configure on a per-region and per-
build basis.

Mapping commands
Table belows shows the new equivalent of the old commands. This is a quick mapping to help those who have
used the previous version of the PowerShell module and need to convert their existing commands.
Make sure to read the definition of each command to get full details of the change since some of the arguments
have also changed.

M ULT IP L AY ERP O W ERSH EL L C O M M A N D ( O L D) M P SP O W ERSH EL L A P I M O DUL E ( N EW )

Add-PFMultiplayerAsset New-PfAsset

Add-PFMultiplayerCertificate Invoke-PfUploadCertificate

Enable-PFMultiplayerServer Enable-PfMultiplayerServer

Get-PFMultiplayerAsset Get-PfAssetSummary

Get-PFMultiplayerBuild Get-PfBuild

Get-PFMultiplayerCertificate Get-PfCertificateSummary

Get-PFMultiplayerContainerImages Get-PfContainerImage

Get-PFMultiplayerImageTags Get-PfContainerImageTag

Get-PFMultiplayerQosServer Get-PfQosServer

Get-PFMultiplayerServer Get-PfMultiplayerServer

Get-PFTitleEntityToken deprecated

New-PFMultiplayerBuild New-PfBuild

New-PFMultiplayerServer Request-PfMultiplayerServer
M ULT IP L AY ERP O W ERSH EL L C O M M A N D ( O L D) M P SP O W ERSH EL L A P I M O DUL E ( N EW )

Remove-PFMultiplayerAsset Remove-PfAsset

Remove-PFMultiplayerBuild Remove-PfBuild

Remove-PFMultiplayerCertificate Remove-PfCertificate

Remove-PFMultiplayerContainerImageTag Invoke-PfImageUntagContainer

Set-PFTitle Set-PfTitle

See also
Walkthrough: Deploy builds using PowerShell/API
Deploy a build using Game Manager
Create your first server
Wrapper sample
Samples and resources
Create and deploy Linux container images
5/24/2022 • 6 minutes to read • Edit Online

This topic outlines specific steps to help you create and deploy Linux container images.
As described in Create VMs, you configure VMs to be automatically spinned up as game servers globally
according to your budget and demand when using our service. In order to do so, you do not explicitly create
VMs but define parameters that determine how they get created on your behalf. This process is called deploying
or creating a build.
PlayFab Multiplayer Servers can deploy both Linux-based and Windows-based game servers. The way builds
are deployed for Linux containers are similar to Windows containers with a few important differences. To learn
more, see Windows and Linux container image differences. If you want to use PowerShell/API to manage Linux
containers, see Manage Linux container images using APIs.
When using Linux-based game servers, instead of using a managed container image, you have to create and
upload your container image to a container registry. To make it easy for you to upload containers, your account
comes with a Azure container registry.

Required knowledge
Docker containers

Set up your Windows development device


This step is needed only if you want to use Windows development device to create Linux container images.
Alternatively, you can use Linux OS devices, VMs, or dual-OS systems with Docker installed.
Windows Subsystem for Linux (WSL) enables you to use your development device in the familiar Windows
environment to author and manage Linux container images. Using WSL means that you would not need an
overhead of a traditional Linux virtual machine or dual-boot setup.
1. Install WSL 2. Make sure that you have restarted your machine and are using WSL 2. You also need to have
successfully installed the Linux kernel update package.
2. Install a Linux distribution that uses WSL. Although our VMs use Ubuntu, you can select any distribution you
want for your container image. Consider using Ubuntu 20.04 LTS or later versions.
3. Install Docker Desktop for Windows with WSL 2. For direct download link, go to Docker Desktop for
Windows (external).
Verify WSL 2 set up
Open PowerShell
Run wsl -l -v to check that both docker-desktop and ubuntu applications are running WSL 2 (version 2)
Verify Docker set up properly for WSL
Open WSL terminal
Run docker version to confirm that Docker is installed and OS used is Linux
TIP
For developing and debugging Linux C++ applications, use WSL in Visual Studio 2019.

Get your PlayFab container registry login credentials


The Azure container registry account is associated with your PlayFab account. Only you have access to the
containers uploaded there.
In Game Manager, select your game title, then Multiplayer > Ser vers . Next, select New build on the right
to open the build creation page.
Select Linux as the virtual machine operating system.
Take note of the login credentials—name, password, and customer5555555.azurecr.io, as this information is
needed later

If you wish to use PowerShell/API, call the GetContainerRegistryCredentials API to retrieve a container registry
address, user name, and password.

Create and push Linux container images to Azure Container Registry


These steps help you create and push your custom Linux container image.
Integrate your game server application with GSDK
Similar to using Windows servers, you have to integrate your game server code with the PlayFab Multiplayer
Server SDK (GSDK). This can be part of your container image.
For instructions, see Author a game server build and Integrating your title with PlayFab Game Server SDK
(GSDK).
Create a Dockerfile
A Dockerfile is a text file with no extension and contains all commands needed to build a given container image.
1. Open Notepad or any suitable editor
2. Add specific commands needed to run and build a container. For an example of this file, see the DockerFile
provided in Wrapper sample. For more information on how to create this file, see Dockerfile format (external)
and Best practices when creating Dockerfile (external)
3. Save file as a Dockerfile, ideally in an empty folder/directory. You should add other files that are needed to
build the container image into this folder.
Saving instructions when using Notepad :
Select File > Save as... to open up the save options
Go to the folder you want to save the file in
Under File name:, use "Dockerfile" , including the quotes.
For Save as type:, select All Files
Select UTF-8 encoding
Select Save
Build and upload Linux container image
1. Open your Linux terminal, making sure that you have installed Docker.
2. Run the following Docker commands using the login credentials obtained from the earlier step. Then follow
the instructions on screen to enter your username and password.

docker login customer5555555.azurecr.io

docker login logs you into the Azure container registry as shown in Game Manager.

username: customer5555555
password: HRDFOdIebJkvBAS+usa55555555

3. Build the container image


Run the command below to build the container image using the Dockerfile in the folder/directory you are in.
Note that there is a "." at the end of docker build command.
The -t flag specifies the name:tag information for your new container image. They will be used if the build
succeeds. If there are build errors, you have to fix them before moving on to the next step.
In the example below, the repository name is customer5555555.azurecr.io/pvp_gameser ver and tag is v1 .
For more information, see docker build command reference (external link) and Building Dockerfile (external
link).
When using WSL, the Windows C: drive is mounted at /mnt/c.
Then run cd /mnt/c/path/to/your/Dockerfile to switch to the path where your Dockerfile is. For more
information, see Accessing C drive.

docker build -t customer5555555.azurecr.io/pvp_gameserver:v1 .

TIP
When using Linux, run pwd to find out which directory you are currently at.

4. Upload the container image


Run the below commands to push the image to your Azure PlayFab Container registry. Select a meaningful and
helpful name:tag combination for your uploaded container image. Then use docker push or another container
registry client, to upload your container to the Azure PlayFab operated registry.

docker tag hello-world customer5555555.azurecr.io/pvp_gameserver:v1


docker push customer5555555.azurecr.io/pvp_gameserver:v1

Check that your container is uploaded


After the container is uploaded, go back to the New Build page in Game Manager and select Refresh Images .
You would be able to see the image in the list and select it. Alternatively, you can use the ListContainerImages
API call to list your uploaded container images.
Now you're ready to deploy servers. For instructions, see PlayFab portal—Game Manager and Using
PowerShell/API.

Windows and Linux container image differences


For many developers, using Windows managed container is the preferred simple and default choice. However,
Linux container images deployed on virtual machines enjoy a cheaper hourly rate.

NOTE
You are able to fully customize your game servers whether you are using Windows or Linux container images. When using
Windows servers, you customize the managed container image by uploading assets.

The table below lists some differences when creating and using them.

DEVELO P ER O P T IO N S W IN DO W S L IN UX

Development device OS Windows OS Windows Subsystem for Linux (WSL) or


Linux OS (using dual-OS or VMs)

Container image Straightforward deployment using our Additional work is needed because you
managed container image. You can still have to create your own custom
customize the container by uploading container image which gives you
additional files as assets. complete control.

Manage Linux container images using APIs


You can use APIs to manage Linux container images. For the rest of build lifecyle (viewing usage, updating
regions and standingBy configurations, deletion), manage them using Game Manager.
GetContainerRegistryCredentials: Retrieve a container registry address, user name, and password
ListContainerImages and ListContainerImageTags: Ensure your new image and tag are listed (sometimes it
might take a couple of minutes for image to be fully registered in the system)
CreateBuildWithCustomContainer: Create a build with a custom container. Specify the tagged image you
uploaded earlier. Ensure the following properties are set on the request:
ContainerImageReference - The image name and tag that was uploaded earlier (and is visible in
ListContainerImages and ListContainerImageTags above).
ContainerFlavor - "CustomLinux"
ContainerRunCommand (Optional) - In case your container doesn't have a default command that it
runs, this can be used to provide the command to run, along with any arguments.
See also
Intro to docker containers
Create your first server
Resources and samples
PlayFab Multiplayer Server SDKs
API Reference
Lifecycle of multiplayer server builds
5/24/2022 • 2 minutes to read • Edit Online

A build can exist in one of the following states:


Unhealthy : One or more configured regions are in an unhealthy state.
Deploying : The following conditions are met:
No region is in an Unhealthy state.
One or more regions are in Deploying state.
DeletingRegion : The following conditions are met:
No region is in an Unhealthy state.
No region is in Deploying state.
One or more regions are in Deleting state.
Deployed : All configured regions are in Deployed state.
The transitions between these states are depicted in the following image, and described below:

1. Deploying/Deployed Regions
Deploying -> Deployed : All regions in Deploying are now in a Deployed state.
Deployed -> Deploying : One or more new regions were configured for the build. The new regions
are in Deploying state.
2. Deploying -> Unhealthy : One or more regions which were in Deploying state are now in Unhealthy
state.
3. Deploying/Deleting Regions
Deployed -> DeletingRegion (rare scenario): Regions which were in Deploying were requested to
be deleted.
DeletingRegion -> Deploying (rare scenario): All regions in Deleting completed deletion, and new
regions were added which are the new regions in Deploying state.
4. Deployed/Deleting Regions
Deployed -> DeletingRegion : One or more regions were requested to be deleted.
DeletingRegion -> Deployed : All regions that were requested to be deleted have been deleted. The
rest of the regions are in Deployed state.

NOTE
Start and Deleted are internal states and are not exposed.
Lifecycle of a multiplayer server build region
5/24/2022 • 2 minutes to read • Edit Online

A build region can exist in one of the following states:


Initialized : The PlayFab multiplayer service has recorded the configuration for the region.
Deploying : A small number of VMs are being provisioned in the region in order to validate the build.
Deployed : The initial set of VMs have all completed loading the game servers and at least one game server
has reported a StandingBy status (via the ReadyForPlayers API call in GSDK).

NOTE
Even though a build region may configured for say 50 standBy servers, a build region will be marked as
Deployed , even if only one game server has reported StandingBy .

Deleting : The region is marked for deletion. All VMs are being de-provisioned.
The transitions between these states are depicted in the following image and described below:

1. Initialized -> Deploying : StandBy servers have been configured to be > 0 . A few VMs are being
provisioned in the region, and the build is being validated on those VMs (propping the assets and ensuring
game server can reach StandingBy state).
2. Deploying -> Deployed : At least one game server in the region has reached a StandingBy state, thus
validating the build (for that region).
3. Deploying -> Unhealthy : One of the following occurred:
All the initial set of VMs (from Step 1 above) are deemed Unhealthy . Some reasons include:
None of the game servers have sent a heartbeat via GSDK for more than 10 minutes after
being started. This usually indicates that the server is crashing, and you will see a
NoSer verHear tbeat health status for each VM in the region.
The PlayFab Multiplayer Agent itself is crashing, or not being initialized on the VM (rare
occurrence). Essentially the multiplayer service has not received a heartbeat from the Agent for
over 10 minutes.
None of the VMs have reached a Running state (mostly stuck in loading assets) for more than 90
minutes.
None of the game servers have reached a StandingBy state for more than 90 minutes (although they
are sending a heartbeat). This indicates an issue during game server initialization.
4. Deploying -> Deleting : This state transition is uncommon, and occurs when the developer requests to
remove a region while it is still deploying.
5. Deployed -> Deleting : The region was removed from the build configuration. Removing a build is
equivalent to removing each region from it (as far as build region status is concerned).
6. Unhealthy -> Deleting : The region was removed from the build configuration. Removing a build is
equivalent to removing each region from it (as far as build region status is concerned).

NOTE
Start and Deleted states are internal to the system and are not exposed.
If the number of standby servers for a region is configured to be 0 , the region will remain in the Initialized state.
In rare unexpected cases (outages), we might see a transition from Deploying to Unhealthy for a brief period.
Lifecycle of a multiplayer server
5/24/2022 • 3 minutes to read • Edit Online

Game Server SDK (GSDK) and game server process lifecycle


Game server lifecycle in PlayFab Multiplayer Servers (MPS) is tightly connected to the GSDK methods your
game server is calling as well as the state of the game server process.

NOTE
For more information on integrating your game server with GSDK, check the docs here.

At a minimum, your game server can integrate GSDK and run great on MPS just by calling the
ReadyForPlayers GSDK method. However, we recommend calling Star t as well when your game server
process starts so MPS is aware that the game server is initializing. Calling Star t is important in the case of a
game server that takes time to start, since MPS will take down the server if it does not receive heartbeats in a
timely manner when the game server starts.

States of a game server


These are the main states of a game server in MPS:
Initializing : Game server transitions to this state when it calls the Star t() GSDK method. In this state, the
game server is starting to load the necessary assets. In this state, the GSDK starts sending heartbeats to MPS.
StandingBy : Game server transitions to this state when it calls the ReadyForPlayers() GSDK method. This
method should be called when all the necessary game assets have been loaded. Essentially, this state signals
to MPS that the game server is ready to be allocated, so players can connect to it.
Active : Game server transitions to this state when it is allocated by using the RequestMultiplayerServer API
call. This state implies that players can connect to the game server and enjoy the game. The fact that the
game server is active means that it will not be taken down during potential Build scale downs (i.e. if the
standingBy number is decreased).
Terminating : This is the state that the game server transitions when the ShutDownMultiplayerServer API is
called. This state implies that the game server is shutting down and will not be available for players to
connect to.
Game server process can terminate either gracefully or via a crash. This can happen at any state. MPS will:
remove the container/process running this game server
collect and upload the game logs so they are ready for archival (more info)
will create a new container/process in its place to replace the one that was terminated

NOTE
A Game server can never transition back to StandingBy state when it is in the Active state. Once the game state is set to
Active, the only way to get a new game server in StandingBy state is if your game server process exits.

Terminating a game server process


When the game session ends, you should gracefully terminate the game server process so you can get a new
game server. If the game server process crashes, MPS will create a new game server process to replace the one
that crashed. In the event that the game server is stuck or frozen, you can always call the
ShutDownMultiplayerServer API to manually terminate the game server process. This API should be called only
when the game server process cannot terminate by itself. When you call this API, you will see the game server
transitioning to "Terminating" and "Terminated" state. Moreover, any servers stuck in the terminating or
terminated state will be replaced by the system after a period of time.

NOTE
There is a method call on GSDK that, if used, will mark the game server as Unhealthy. At this time it is ignored by MPS,
but this may change in the future. If this feature is critical for you, please leave a note at the GSDK repository here.

Verifying GSDK integration with your game server


MPS has a developer tool to test GSDK integration for game servers. Tool is called LocalMultiplayerAgent ,
you can download it here and you can check the docs here for more information.
GSDK samples
To check GSDK samples demonstrating integration with popular game engines, you can check the MpsSamples
repository here.
OS patch updates for Windows
5/24/2022 • 2 minutes to read • Edit Online

Playfab Multiplayers Servers managed Windows containers undergo a methodical OS patch update process to
ensure game servers are operating with the latest security updates. Each month, Azure Compute certifies a
Windows OS image that is integrated into Multiplayer Servers for developers to choose from the "Windows
Server Core Preview" toggle during the build creation process. Developers are encouraged to test their non-
production game servers built with the "Windows Server Core Preview" option.

After 30 days, Multiplayer Servers will migrate the Windows Server Core Preview to the Windows Server Core
image option - signaling a PlayFab approved OS image for production readiness. This process will repeat every
30 days, cycling an OS preview image to its mainline OS core image. If a game server built with OS core version
that doesn’t match PlayFab’s OS core version, PlayFab will auto-update your game build server with the latest
mainline OS core image. This process is applied automatically with no build changes required by the developer.

Patch update cycle


The following image illustrates the OS patch level update cycle.

STA GE STA K EH O L DER DESC RIP T IO N

1 Customer Continuous integration & test process


deploys production game builds with
OS core and tests game builds with OS
preview
STA GE STA K EH O L DER DESC RIP T IO N

2 Azure MPS validates new published Windows


OS patch

3 MPS PlayFab replaces MPS OS preview with


Windows OS patch

4 MPS PlayFab replaces MPS OS core with


MPS OS preview 30-days prior

5 MPS PlayFab auto-updates game builds


with OS Core

Best Practices
1. Developers are encouraged to create and test their non-production game server builds with the OS preview
image option.
2. Developers with a mature build and continuous integration & deployment process should take into
consideration that OS image updates cycle every 30 days

Constraints
1. The patch update process occurs monthly
2. Developers cannot opt out of the monthly OS patch level updates
3. The patch update process is only applicable to Windows managed containers and does not apply to custom
containers or Linux.

NOTE
Game server builds are immutable once created. Therefore, developers cannot toggle between OS image preview and
OS image core.
A game server operating in production will be auto-updated to the latest OS core image version if the version that the
build was made is older than the latest. This will be applied automatically for any new multiplayer server allocation
request only.
Managing a build alias and allocating to it
5/24/2022 • 4 minutes to read • Edit Online

A build alias is a management layer on top of builds, which allows calls to RequestMultiplayerServer to be
distributed over multiple builds in a controlled fashion. This can improve the simplicity and reliability of build to
build upgrades and several other scenarios listed below. Aliases achieve this by specifying a list of build ids
along with the weight of each one. The weight represents the ratio of allocation calls that should be forwarded
to the corresponding build.
Safe deployment that is backwards compatible
This is the most common scenario for a build to build upgrade, where you are updating the game server and
retail clients are compatible with both servers.
Clients will reference Alias 1, which would have the following configuration:
Build 1: Weight = 1
Once Build 2 is created, Alias 1 will be changed to be:
Build 1: Weight = 8
Build 2: Weight = 2
You can gradually change the weights until all new server requests are fulfilled by Build 2. At this point the
weight for Build 1 is 0 and can be removed from the alias.
A typical use case for an alias is affinitizing them to a client compatibility version and game mode. For example
"DeathMatch client 2.2 RETAIL." Aliases allow you to manage this higher-level abstraction while continuously
updating the builds that power this experience. Aliases also make it easier for you to roll-back builds if
necessary.
Deployment that is not backwards compatible
In this case you want to update the game server at the same time you are updating game clients, as your current
game clients are not compatible with the old server build. Transitioning from one build to another would be
done as follows:
Old clients will reference Alias 1, which would have the following:
Build 1: Weight = 1
Once Build 2 is created, new clients will reference Alias 2, which would have the following:
Build 2: Weight = 1
In this scenario aliases are used similarly to builds, and their multiplexing functionality is not used.
Blast deployment that is backwards compatible
This is similar to the backwards compatible build to build upgrade scenario, but with a more sudden switch in
demand behavior. Transitioning from one build to another would be done as follows:
Clients will reference Alias 1, which would have the following:
Build 1: Weight = 1
Once Build 2 is created, Alias 1 will be changed to be:
Build 1: Weight = 0
Build 2: Weight = 1
Testing a deployment that is backwards compatible
When you want to update the game server, and the client version is compatible with both servers, but you wants
to test the second version before deploying it at scale for all players. Testing and transitioning from one build to
another could be done as follows:
Clients will reference Alias 1, which would have the following:
Build 1: Weight = 1
Once Build 2 is created. Testing clients would reference Alias 2, which would have the following:
Build 2: Weight = 1
Once Build 2 is verified. Alias 1 will be changed to be:
Build 1: Weight = 8
Build 2: Weight = 2
Gradually build 2 would be weighted more and absorb all traffic.

Fallback to other builds and regions


Aliases can make your multiplayer server deployments more resilient, by allowing for fallback across multiple
builds. For example, assume an allocation request targeting a build alias ranks EastUS as region #1, and West US
as region #2. This build alias provides similar weights to two builds, Build 1 and Build 2.
Assume that for a given allocation Build 1 is selected.
1. Allocation in East US for Build 1 is tried.
2. If #1 fails, allocation in East US for Build 2 is tried.
3. If #2 fails, allocation in WestUS for Build 1 is tried.
4. If #3 fails, allocation in WestUs for Build 2 is tried.
Especially as you gradually upgrade from one build to another, this fallback behavior is optimized so that players
get the lowest latency server even if one of the builds is having trouble.

Manage a build alias with PlayFab REST APIs


NOTE
You can now manage build aliases in Game Manager. To get started, see Builds overview page

1. Create a build alias by using the API.


API:

POST https://titleId.playfabapi.com/MultiplayerServer/CreateBuildAlias

Sample body:
{
"AliasName":"TestingAlias",
"BuildSelectionCriteria":
[{
"BuildWeightDistribution":{"9a8a4584-c81a-479c-9ef9-16d3743f7ca7":"1"}
}]
}

Sample response:

{
"AliasId":"97d2b0a5-7c04-4593-8451-66bbb97f94b6",
"AliasName":"TestingAlias",
"BuildSelectionCriteria":
[{
"BuildWeightDistribution":{"9a8a4584-c81a-479c-9ef9-16d3743f7ca7":"1"}
}]
}

Build Alias Id is provided as par t of the response.


2. Update any parameter of the build alias.
API:

POST https://titleId.playfabapi.com/MultiplayerServer/UpdateBuildAlias

Sample body:

{
"AliasId":"97d2b0a5-7c04-4593-8451-66bbb97f94b6",
"AliasName":"TestingAliasRenamed",
"BuildSelectionCriteria":
[{
"BuildWeightDistribution":{"9a8a4584-c81a-479c-9ef9-16d3743f7ca7":"1",
"7ac7f347-3d61-9fe9-c974-a18c4854a8a9":"1"}
}]
}

Sample response:

{
"AliasId":"97d2b0a5-7c04-4593-8451-66bbb97f94b6",
"AliasName":"TestingAliasRenamed",
"BuildSelectionCriteria":
[{
"BuildWeightDistribution":{"9a8a4584-c81a-479c-9ef9-16d3743f7ca7":"1",
"7ac7f347-3d61-9fe9-c974-a18c4854a8a9":"1"}
}]
}

3. Delete a build alias.


API:

POST https://titleId.playfabapi.com/MultiplayerServer/DeleteBuildAlias
Sample body:

{
"AliasId":"97d2b0a5-7c04-4593-8451-66bbb97f94b6"
}

4. List build aliases.


API:

GET https://titleId.playfabapi.com/MultiplayerServer/ListBuildAliases

Sample response:

[{
"AliasId":"97d2b0a5-7c04-4593-8451-66bbb97f94b6",
"AliasName":"TestingAliasRenamed",
"BuildSelectionCriteria":
[{
"BuildWeightDistribution":{"9a8a4584-c81a-479c-9ef9-16d3743f7ca7":"1",
"7ac7f347-3d61-9fe9-c974-a18c4854a8a9":"1"}
}]
}]

Allocate using a build alias


To allocate using a build alias one must simply specify the build alias Id in the RequestMultiplayerServer call.
API:

POST https://titleId.playfabapi.com/MultiplayerServer/RequestMultiplayerServer

Sample body:

{
"SessionId":"6a07440c-7bcc-4e23-8b81-4934543ff966",
"PreferredRegions":["SouthCentralUs"],
"BuildAliasParams":
{"AliasId":"97d2b0a5-7c04-4593-8451-66bbb97f94b6"}
}
Archiving and retrieving multiplayer server logs
5/24/2022 • 2 minutes to read • Edit Online

In several scenarios, you may want to keep logs or other arbitrary file content from your game servers for later
analysis.
There are two ways you can gather your logs either through the Game Server SDK or Game Manager. The SDK
provides an API that allows you to write to a log file or access a logging directory.
See Integrating game servers with the PlayFab game server SDK (GSDK) to learn more about these logging
mechanisms. To programmatically gather your logs, use the ListArchivedMultiplayerServers method. The result
will give you the information for the servers, next you'll need to call GetMultiplayerServerLogs method with the
Server ID as the input.
Archived Ser vers is the vehicle for retrieving these logs after the game server has terminated. These logs are
kept for 28 days after the termination of your game server.
To do this using Game Manager first, go to the Builds page in the Multiplayer tab , and select the build that is
associated to the server you're looking for.

Next, select the Ser vers tab located at the top and you'll see a list of VM's and servers, select the Archived
ser vers link at the bottom
Use the Search bar at the top of the page and use either the Host ID or VM ID to download logs for a specific
server.
VM Metrics (preview)
5/24/2022 • 4 minutes to read • Edit Online

Introduction
Game developers sometimes need access to system level metrics (CPU/RAM/etc.) for the Virtual Machines that
are created as part of their Builds. These metrics can provide unique insights to the game developer during the
development of their multiplayer game server. Given these metrics, a game developer can make informed
decision about utilizing VM resources.
Performance metrics can support various development scenarios:
1. Using CPU and memory utilization data to measure the resource needs of multiplayer servers, so game
developer can properly calculate the optimal number of game servers on a specific Virtual Machine SKU
(type)
2. Using network counters to detect an irregular network environment, such as attempted DDoS attacks or
other network congestion
PlayFab Multiplayer Servers service supports a limited number of system metrics via the VM Metrics (preview)
feature.

IMPORTANT
This feature is currently experimental and offered as a preview. This means that parts of it can change at any time. We are
significantly iterating on the experience and asking customers for feedback.

Usage
VM metrics for a Build can be enabled in two ways, depending on how a Build is created:
1. Using Game Manager, you can enable the "Virtual machine metrics preview" checkbox on the "New Build"
Game Manager page.
2. Using the PlayFab Multiplayer Servers API, you can set the property "IsEnabled" to true in the following API
objects:
InstrumentationConfiguration in the CreateBuildWithManagedContainer API call for a Windows Build with
containers
InstrumentationConfiguration in the CreateBuildWithProcessBasedServer API call for a process-based
Windows Build
LinuxInstrumentationConfiguration in the CreateBuildWithCustomContainer API call for a Linux Build
When VM metrics feature is enabled for a Build, it will remain enabled for the entire lifetime of the Build. You
can't enable/disable VM metrics for a Build after it has been created.
Windows
On Windows, VM metrics collection is a feature of the existing PlayFab container/process orchestrator called
VmAgent . VmAgent periodically (every 10 seconds) runs a task that will query the following system performance
counters:
1. Available MBytes
2. % Processor Time
3. % User Time
4. Disk Reads/sec (for drive D:)
5. Disk Writes/sec (for drive D:)
6. Bytes Received/sec
7. Bytes Sent/sec
Collected counter values are sent to our internal metrics collector running on the VM. The collector aggregates
and sends them to our internal backend so they can be presented to the user on Game Manager.
Linux
On Linux, we're using the open-source telegraf agent for collecting and processing metrics. Telegraf collects
metrics every 10 seconds and emits them to our internal collector agent every 60 seconds. For reference, below
you can see the contents of the telegraf.conf configuration file we're using, feel free to consult the official telegraf
docs for further details.
We're also using an internal utility called telegraf-geneva-processor that emits the diff value for counter level
metrics (like net_bytes_recv) metric. Emitting the diff value instead of the actual counter value results in better
visualization in the provided Game Manager graphs.
[agent]
interval = "10s"
round_interval = true
metric_batch_size = 1000
metric_buffer_limit = 10000
collection_jitter = "0s"
flush_interval = "60s"
flush_jitter = "0s"
precision = ""
debug = false
omit_hostname = true

[global_tags]
titleID = "TITLE_ID"
buildID = "BUILD_ID"
vmID = "VM_ID"

# consult man proc for details


# https://github.com/influxdata/telegraf/tree/master/plugins/inputs/cpu
[[inputs.cpu]]
percpu = false
totalcpu = true
name_prefix = "telegraf_"
fieldpass = ["usage_system", "usage_user"]

[[inputs.mem]] # https://www.linuxatemyram.com/
fieldpass = ["available_percent"]
name_prefix = "telegraf_"

[[inputs.net]] # /proc/net/dev
fieldpass = ["bytes_sent", "bytes_recv"]
name_prefix = "telegraf_"
interfaces = ["eth0"]
tagexclude = ["interface"]

# https://github.com/influxdata/telegraf/tree/master/plugins/inputs/diskio
[[inputs.diskio]] # /proc/diskstats
fieldpass = ["reads", "writes"] # number of reads and writes on sdb device
devices = ["sdb"] # sdb device contains everything (including container storage) apart from /mnt
name_prefix = "telegraf_" # which is the place where some of our shared folders are

# grab the allocated percentage from VmAgent. Be aware that this must be in influx format
[[inputs.http]]
urls = ["http://localhost:56001/v1/metrics/allocatedpercentage"]
name_prefix = "telegraf_"
data_format = "influx"
tagexclude = ["url"]

# send all telegraf data to internal collector


[[outputs.socket_writer]]
address = "unix:///var/etw/mdm_influxdb.socket"
data_format = "influx"

# write this data to a file. This might be removed in the future


[[outputs.file]]
files = ["/tmp/PerformanceMetrics.csv"]
data_format = "influx"
rotation_max_size = "100MB"
rotation_max_archives = 5

[[processors.execd]]
command = [
"/usr/bin/telegraf-geneva-processor",
"-configFile=/etc/telegraf/telegraf.geneva.processor.conf"
]
This telegraf.conf configuration enables the telegraf agent to collect the below metrics:
1. cpu_usage_system
2. cpu_usage_user
3. memory_available_percent
4. net_bytes_recv_diff (network bytes received for eth0)
5. net_bytes_sent_diff (network bytes sent for eth0)
6. diskio_reads_diff (number of reads for sdb)
7. diskio_writes_diff (number of writes for sdb)
Similar to Windows, telegraf sends the collected counter values to our internal metrics collector. The collector
aggregates and sends these values to our internal backend so they can be presented to the user on Game
Manager.
Allocation Percentage
In both Windows and Linux VMs, we're emitting a metric called Allocation Percentage. The value of this metric is
calculated by dividing the number of Active servers with the Total number of servers on the VM. This metric is
meant to be used when evaluating and interpreting the reported system metric values. This is because the value
of the system metrics will probably be different on a VM with lots of Active servers compared to a VM with lots
of StandingBy servers.

Viewing VM metrics
When you enable the VM metrics feature for a new Build, metrics will be emitted as soon as the Build is
successfully deployed. You can use the "Virtual Machines" (https://developer.playfab.com/en-
US/<YOUR_TITLE_ID>/multiplayer/server/virtual-machines) page on Game Manager to get a link to display VM
metrics for a specified VM.
You can also access the VM metrics by selecting your build, going to the servers tab, and hitting the menu inline
with the VM you would like to see the metrics on, and select "View Metrics"

How can I submit feedback for this preview feature?


Join us on Discord on the #multiplayer-servers channel, we would love to get in touch and hear your thoughts
about this feature!
LocalMultiplayerAgent overview
5/24/2022 • 2 minutes to read • Edit Online

LocalMultiplayerAgent(LMA) is a helper agent to facilitate faster development iterations by testing or running


your game server on your local machine. Without any cloud connection, LMA can provide mock responses to
the Game server SDK(GSDK) and test your game servers as it's running on PlayFab Multiplayer Servers(MPS).
Here are some examples you can do with LocalMultiplayerAgent:
Verify GSDK integration with your game servers.
Test connection to your game servers
Run a diagnosis on your game servers: Logs and config files generated on each game session
Verify build configuration

Prerequisites
1. Game Server integrated with GSDK.
GSDK facilitates two-way communication between your game server process and the MPS service. To
learn how to integrate game servers with GSDK, see this article. The tutorial uses the Wrapper sample on
GitHub. The Wrapper sample includes a fake game and GSDK. To download the sample, see PlayFab
Wrapper Sample.
2. LocalMultiplayerAgent (LMA) toolset.
Download the latest release and extract it to the desired folder. (such as C:\PlayFabVmAgent)
3. [Optional] Install Docker Desktop on Windows.
LMA can debug Linux/Windows container game servers using Docker for Windows. You can skip this
part if you want to run your game server as a process (run executable game server) instead of a
container.

Next steps
Run LocalMultiplayerAgent in Process Mode
In Process mode, LMA will run an executable game server and directly communicate with it without the
need to set up Docker.
Container knowledge isn't required - you don't need to create any program that runs in a container.
Run LocalMultiplayerAgent in Container Mode
In Container mode, LMA will run and test a game server running in a [Windows/Linux]container.
How to run a game server using
LocalMultiplayerAgent in Process mode
5/24/2022 • 4 minutes to read • Edit Online

This tutorial describes how to:


Create a Build using the Wrapper sample
Configure MultiplayerSettings.json
Run LocalMultiplayerAgent
Test your game connection

Create a Game Build


To test your game servers using LocalMultiplayerAgent(LMA), your need to create a game build and save it as
archive format. To make it easier for you, we provide the Wrapper sample with an instruction and PowerShell
script.
Next, follow the step "Wrapping an existing game server using the wrapper app" to get your game server ready
for this tutorial.

Configure MultiplayerSettings.json
Navigate to the folder where you extracted the LMA toolset and open the MultiplayerSettings.json file. This file is
a build configuration mock file that simulates the build on MPS.
You can populate json using LMA MultiplayerSettings.json Generator. The Generator is a simple web page that
creates json based on your options. You can find the Generator under extracted folder of LMA.
Here's the example of MultiplayerSettings.json for Wrapper sample to run LMA in Process mode.
{
"RunContainer": false, // Set RunContainer to false if you are running LMA in Process mode.
"OutputFolder": "C:\\output\\WindowProcess", // Path where config files and logs will be generated from
LMA at each run
"NumHeartBeatsForActivateResponse": 10, // default value
"NumHeartBeatsForTerminateResponse": 60, // default value
//the server will run in stand-by mode for 10 heartbeats and stay in active state for 35 heartbeats.
"TitleId": "59F84", // default value
"BuildId": "8624d52e-87a1-4a12-b7f6-b92720ef8919", // default value
"Region": "EastUs", // default value
"AgentListeningPort": 56001, // default value
"AssetDetails": [
{
"MountPath": "", // Mount Path is only required for Container mode. leave it as blank.
"SasTokens": null,
"LocalFilePath": "D:\\gameassets.zip" // where your game server is located as an archive format.
}
],
"ProcessStartParameters": {
"StartGameCommand": "wrapper.exe -g fakegame.exe arg1 arg2"
// shell command to run Wrapper. Command will be executed where game asset is extracted.
// Make sure the StartGameCommand provided above is an example of the Wrapper sample.
},
"PortMappingsList": [
[
{
"NodePort": 56100, // default value
"GamePort": {
"Name": "game_port",
// Port name is already defined in the Wrapper sample. Wrapper will grab the port information
using game_port via GSDK while it's running.
"Protocol": "TCP"
}
}
]
],
}

Make sure to update the following fields correctly in the MultiplayerSettings.json to run LMA in Process mode.
LocalFilePath- Full Local Path (on your workstation) to the game server asset zip file created earlier, for
example: D:\MyAmazingGame\asset.zip (note that backslashes need to be escaped for JSON formatting).
StartGameCommand - The StartGameCommand path for a process is a relative path. The working directory
will be where your game asset is extracted.
PortMappingsList - These are the ports that are available to your game while running.
NodePort is the port that is opened on your workstation
GamePort.Number isn't required for Process mode. Port number will be bound to Node Port via
GSDK when your game server is running. In the real scenario, MPS will bind the port dynamically
for each Process-based game session.
Set the GamePort.Name to the same value as defined in your game server. You can check the GSDK
config at runtime for the value with the key GamePort.Name. If you're using the Wrapper Sample,
port name is already defined to "game_port", so you should set the same value here.
GamePort.Protocol - Specify protocol type: TCP or UDP
OutputFolder - Path to a drive or folder where the outputs and config files are generated. Ensure that
there's sufficient space available since the game server will be extracted under this path. If not specified,
the agent folder is used.
AgentListeningPort - This is the port for the LMA to communicate with the game server. Any open port
will work, 56001 is a default value. If you have another process binding to 56001, you must change this
value or kill the other process on port 56001.
ResourceLimits - not required for Process mode.
MountPath - not required for Process mode.
SessionCookie (optional) - Any session cookie that is passed to your game server as part of the
RequestMultiplayerServer API call. In the real scenario on MPS, after the connection is established, server
will notify the client to load corresponding resources from SessionCookie.

Run LocalMultiplayerAgent
Now you're ready to run LocalMultiplayerAgent.
In a PowerShell window :
Navigate to directory under LMA that contains LocalMultiplayerAgent.exe.
Run LocalMultiplayerAgent.exe . At this point, LMA sets up the http listener, unzips the game asset, and
starts the game server in a separate process.

If you are running your game server as a Process, the Windows Firewall may pop-up and ask if you
want to allow traffic to the NodePort you specified. If you want to avoid that, you can either run the
LocalMultiplayerAgent in admin mode or enable the port in the firewall.

LMA will wait for heartbeats from the GSDK integrated with your game server. If the GSDK is integrated
correctly, LMA prints the outputs as following order:
1. CurrentGameState - Initializing
(This may not show up if your game server directly calls GSDK::ReadyForPlayers and doesn't call GSDK::Start)
2. CurrentGameState - StandingBy
3. CurrentGameState - Active
4. CurrentGameState - Terminating

To learn more about states of a game server, see What is Game Server Lifecycle of PlayFab Multiplayer Server.
If the shutdown callbacks are set up correctly, your game server exits soon after the state is set to terminating.
It's important to verify that the game server exits to avoid ungraceful shutdowns on the PlayFab platform.
The LMA should also terminate along with the game.

Test connection to your game


Once LMA prints CurrentGameState - Active , you can connect to your game server using IP address
127.0.0.1 and port NodePort on which your game server is listening.
If you're using Wrapper sample, You can test a GET request by entering the address http://127.0.0.1:56100/Hello
into your browser. For more details, check out the Wrapper sample.
You can also update the values of NumHear tBeatsForActivateResponse and
NumHear tBeatsForTerminateResponse in MultiplayerSettings.json to adjust the duration of standing-
by/active state.
How to run a game server using
LocalMultiplayerAgent in Container mode
5/24/2022 • 7 minutes to read • Edit Online

This tutorial describes how to:


Create a [Linux/Windows] Container Build using the Wrapper Sample
Configure MultiplayerSettings.json
Docker setup
Run LocalMultiplayerAgent
Test your game connection

Create a [Linux/Windows] Container Build


If you're unfamiliar with container, see Introduction to Container and Docker.
We'll learn how to package an existing sample as a Windows or Linux container. You'll need to configure
different settings for different platforms (Windows/Linux based Container). Here we'll use the Wrapper sample
and go over the details.
Linux Container Build
You can run the wrapper and fakegame executable on a Linux Build, using Linux containers. In this case, you
need to create a Linux build. To learn how to create Wrapper Linux build, see how to create a Linux container
image
Windows Container Build
LMA will create a Windows Container Build for you. You just need to configure the settings correctly (Check out
later how to configure settings for Windows Container)

Configure MultiplayerSettings.json
Navigate to the folder where you extracted the LMA toolset and open the MultiplayerSettings.json file. This file is
a build configuration mock file that simulates the build on MPS.
You can also populate a json using LMA MultiplayerSettings.json Generator. The Generator is a simple web page
that creates a json based on your options. You can find the Generator under
LocalMultiplayerAgent/SettingsJsonGenerator.
Here's the example of MultiplayerSettings.Json to run the Wrapper sample as Linux Container .
{
"RunContainer": true, // Set RunContainer to true if you are running LMA in Container mode.
"OutputFolder": "C:\\output\\LMAContainer", // Path where config files and logs will be generated from
LMA at each run
"NumHeartBeatsForActivateResponse": 10,
"NumHeartBeatsForTerminateResponse": 60,
"TitleId": "", // default value
"BuildId": "00000000-0000-0000-0000-000000000000", // default value
"Region": "59F84", // default value
"AgentListeningPort": 56001, // default value
"ContainerStartParameters": {
/// replace ImageDetails fields to your own images saved on ACR.
"ImageDetails": {
"Registry": "mydockerregistry.io",
"ImageName": "wrapper",
"ImageTag": "0.1",
"Username": "",
"Password": ""
}
},
"PortMappingsList": [
[
{
"NodePort": 56100,
"GamePort": {
"Name": "game_port",
// The same value of GamePort Name should be also defined in the Wrapper so Wrapper can
get a port information while it's running.
"Number": 80,
"Protocol": "TCP"
}
}
]
],
}

For Windows Container , you don't need to build your container. LMA will package your game server as Windows
Container. You just need to specify the Windows container base image in ImageDetails field and set
LocalFilePath to where your game asset is located on your work station.
"AssetDetails": [
{
"MountPath": "C:\\Assets",
// Mount Path should be "C:\\Assets" for Windows Container.
"LocalFilePath": "D:\\gameassets.zip"
// where your game server is located as an archive format.
}
]

"ContainerStartParameters": {
"StartGameCommand": "C:\\Assets\\wrapper.exe -g C:\\Assets\\fakegame.exe arg1 arg2",
// Your game assets will be extracted under C:\\Assets (default mount path for Windows Container) and
LMA will run your game server with StartGameCommand argument.
// Make sure the StartGameCommand provided above is an example of the Wrapper sample.
"ImageDetails": {
"Registry": "mcr.microsoft.com",
"ImageName": "playfab/multiplayer",
"ImageTag": "wsc-10.0.17763.973.1",
"Username": "",
"Password": ""
// username and password are not required to use MCR image.
}
// LMA will package an existing game sample (path defined in LocalFilePath) as a Windows container.
}

Make sure to update the following fields correctly in the MultiplayerSettings.json to run LMA in Container mode.
LocalFilePath - Full Local Path (on your workstation) to the game server asset zip file created earlier, for
example: D:\gameassets.zip (note that backslashes need to be escaped for JSON formatting). This field is
required for Windows Container as LMA needs to locate your game asset and then package it into a
container.
PortMappingsList - These are the ports that are available to your game while running.
NodePort is the port that is opened on your workstation and will be mapped to the GamePort.
GamePort.Number is the port that your game server needs to bind to when running in a container. For
example, here we set port number as 80 which fakegame.exe will be listening to.
Set the GamePort.Name to the same value as defined in your game server. You can check the GSDK
config at runtime for the value with the key GamePort.Name.
GamePort.Protocol - Specify protocol type: TCP or UDP
Update the GamePort section to match the protocol and port at which your game server is listening for
clients. You can add multiple ports.
ForcePullFromAcrOnLinuxContainersOnWindows- Set true when you want to pull Linux Container Image
from Docker Registry and avoid pulling from the local registry. In most cases, you'd want this set to false.
ContainerStartParameters.ImageDetails - Your game server image can be published on a container
registry or can be locally built. If you want to pull Linux Container image from Docker Registry (For
example, Azure Registry), you need to set value for username and password and set
ForcePullFromAcrOnLinuxContainersOnWindows as true. For Windows Container, username and password
aren't required.
OutputFolder - Path to a drive or folder where the outputs and config files are generated. Ensure that
there's sufficient space available since the game server will be extracted under this path. If not specified,
the agent folder is used.
AgentListeningPort - This is the port for the LMA to communicate with the game server. Any open port
will work, 56001 is a default value. If you have another process binding to 56001, you must change this
value or kill the other process on port 56001.
ResourceLimits (optional) - If specified, docker limits CPU/memory usage. Warning: If your server goes
over the allowed memory, it's killed. ResourceLimits can only be specified in container mode.
SessionCookie (optional) - Any session cookie that is passed to your game server as part of the
RequestMultiplayerServer API call. In the real scenario on MPS, after the connection is established, server
will notify the client to load corresponding resources from SessionCookie.

Docker set up
Run PowerShell scripts to set up the docker networks called "PlayFab" and add firewall rules to communicate
with LocalMultiplayerAgent.
For Linux Container, Run SetupLinuxContainersOnWindows.ps1 .
For Windows Container, Run Setup.ps1 . It will pull down the PlayFab docker image from Microsoft/PlayFab-
Multiplayer.
Note that the first time the script runs, it can take a few minutes to download the container image.

To run this setup successfully, you may have to configure the firewall of any 3rd party antivirus
program that you have installed.

To learn how target the correct docker daemon between Windows and Linux containers, see How to switch
Docker to use Windows/Linux Container

Run LocalMultiplayerAgent
In a PowerShell window :
Navigate to directory under LMA that contains LocalMultiplayerAgent.exe.
Run LocalMultiplayerAgent.exe for Windows Container.
Run LocalMultiplayerAgent.exe -lcow for Linux Container.
(lcow stands for Linux Containers On Windows)
At this point, LMA sets up the http listener and run a container. You can run docker ps command to see
running containers on your machine.
LMA will wait for heartbeats from the GSDK integrated with your game server. If the GSDK is integrated
correctly, LMA prints the outputs as following order:
1. CurrentGameState - Initializing
(This may not show up if your game server directly calls GSDK::ReadyForPlayers and doesn't call GSDK::Start)
2. CurrentGameState - StandingBy
3. CurrentGameState - Active
4. CurrentGameState - Terminating

To learn more about states of a game server, see What is Game Server Lifecycle of PlayFab Multiplayer Server.
If the shutdown callbacks are set up correctly, your game server exits soon after the state is set to terminating.
It's important to verify that the game server exits to avoid ungraceful shutdowns on the PlayFab platform.
The LMA should also terminate along with the game.

Test connection to your game


Once LMA prints CurrentGameState - Active , you can connect to your game server using IP address
127.0.0.1 and port NodePort on which your game server is listening.
If you're using Wrapper sample, you can test a GET request by entering the address http://127.0.0.1:56100/Hello
into your browser. For more details, check out the Wrapper sample.
You can also update the values of NumHear tBeatsForActivateResponse and
NumHear tBeatsForTerminateResponse in MultiplayerSettings.json to adjust the duration of standing-
by/active state.
Troubleshooting
In container mode, if your game server exits immediately with an error similar to "Container ... exited with
exit code 1", but it works fine in process mode, make sure that you've included all required system DLLs in
your asset package.
All logs are located under OutputFolder that is specified in the MultiplayerSettings.json file.
LocalMultiplayerAgent creates a new folder each time it's started, with the timestamp as folder name. All
game server logs emitted via GSDK are located within the GameLogs folder.
If the game server is running in a container, there might be an additional level of directory hierarchy to shift
through.
The GSDK writes debug logs to the GameLogs folder under the OutputFolder . These logs are located within
the GameLogs folder along with the logs output by the game server.
Ensure firewalls (windows and other anti-virus) are configured to allow the traffic over the ports.
If you get an error similar to:
Docker API responded with status code=InternalServerError, response={"message":"failed to create endpoint
<container_name> on network playfab: hnsCall failed in Win32: The specified port already exists". It is
likely there is already a container running on the specified port.
This can happen if LocalMultiplayerAgent exits prematurely. Use the command docker ps to find the
container that is running, and then delete it using docker kill <container_name> .
If you get an error that contains Failed to find network 'playfab' . Try rerunning Setup.ps1
Known Limitations
1. Containers might not terminate at the end of the debugging. If this occurs, run the following PowerShell
commands as Administrator. These commands stop and remove all containers, including those weren't
started by LocalMultiplayerAgent .

docker stop $(docker ps -aq)


docker rm $(docker ps -aq)
Connect directly to debug game servers
5/24/2022 • 5 minutes to read • Edit Online

Many debugging tasks of PlayFab Multiplayer Servers can be done locally using LocalMultiplayerAgent.
However, sometimes the behavior of the game server can differ between the local environment and the actual
service so you would like to connect directly to debug a running server because it is marked as unhealthy or not
performing as expected.
In order to connect to the VM hosting your game server (either Windows or Linux), you can get Remote Desktop
(RDP)/SSH credentials using the "Connect" button on playfab.com web application. You can see this button on
the "Virtual Machines" page on your Multiplayer Build) or using CreateRemoteUser API call.
As soon as you connect to the VM, you can use the console of the operating system to monitor your game
servers. MPS service uses Docker containers to spin up game server processes. To run Docker CLI commands,
you'll need an admin powershell on Windows and sudo su - on Linux.

IMPORTANT
These are advanced Docker container debugging instructions. Using these instructions may break your game servers. We
do not recommend using these commands on containers running your production game servers.
We strongly advise you not to take any dependency on behavior or information you see while debugging the containers.
Only publicly documented APIs and behavior are supported, other things can change without notice.

Instructions for both Windows and Linux


How can I get started with Docker containers?
Regardless if you're developing on Linux or Windows, you should get acquainted with the basics of Docker
containers.
You can watch the official "Get Started" video here (external link) and experiment in an interactive playground on
Katacoda (external link). To learn more about Windows Containers, see Windows and containers.
Once I RDP/SSH into the VM, how can I see a list of my running game servers running in Docker containers?
Use docker ps . You will see container name and hashes as well as port mapping from the VM port(s) to the
Docker container port(s).
How can I see the ports used by my game servers?
This information is listed on docker ps . You will see something like that:

980d7e80457265230a0bf "/bin/sh -c ./cppLin…" About a minute ago Up About a minute 0.0.0.0:30000-


>3600/tcp, 0.0.0.0:30001->3601/udp great_archimedes

In this case, port 30000 on the VM is mapped onto 3600 on the container for TCP whereas 30001 on the VM is
mapped on 3601 on the container for UDP. For more information, see Docker networking.

NOTE
In both Windows and Linux, Docker containers are part of the "playfab" Docker network. You can do docker inspect
network playfab to see information about the network.
How can I see runtime details for a container?
Once you do docker ps you can grab the container name or hash and do docker inspect <nameOrHash> .
You will see lots of information, like the state of the container, the volume binding on the host VM, port bindings,
environment variables passed into the container and more.
How can I get the logs of my game server?
You can use the command docker logs <nameOrHash>. These logs contain everything your app sends to
standard output/standard error streams. Bear in mind that these logs exist only for existing containers. If your
game server crashes, our monitoring process in the VM will delete this container and create a new one.
Consequently, it's a better practice to use GSDK to log from inside your game server. To learn more, see Logging
with GSDK and Archiving and retrieving multiplayer server logs to access the logs from terminated game
servers.
Can I connect "inside" a running container to see what's going on?
Yup! You can do docker exec -it <nameOrHash> powershell on Windows and docker exec -it <nameOrHash>
bash on Linux. There, you get access to a command line process in the container where you can issue native
commands to debug/diagnose issues.
For this command to work on Linux, Bash shell must be installed in your base container. If it isn't, you can use
Bourne shell by running docker exec -it <nameOrHash> sh .
How can I see the ports that are open on my container?
Once you are connected "inside" the container, you can use netstat -ano on Windows and netstat -tulpn on
Linux when you have a command line process inside your container (check the previous instruction).
If this command doesn't work on Linux, try installing netstat by apt update && apt install net-tools . On
Linux, you can use nestatst -tulpn inside the VM to see that the ports are indeed open. Recall that VM ports
will be different than container ports, you can see this port mapping with docker ps for your containers.

Linux specific instructions


How can I see diagnostics about my container?
You can install apt install procps and then run:
ps -aux for the current running processes (observer that your main process in the container has a PID of 1. If
this process dies, your container will be gone)
top for real time process information
How can I monitor TCP and UDP packets?
Consider using a tool like TCPdump (external link) utility.
Run apt update && apt install tcpdump to install it. In order to use it for a specific port, run tcpdump
por t 7777 for TCP and tcpdump udp por t 7778 for UDP.
You can use tcpdump both from inside the VM and from inside the container. However, ensure that you will be
monitoring for the correct port value, since there is a port mapping between VM ports and container ports.

Windows specific instructions


How can I determine the required DLLs that need to be in my asset package?
For instructions, see Determining required DLLs. This article is also useful if your game server fails to start
because of one or more missing DLLs.
LocalMultiplayerAgent is crashing and restarting my Docker container with no error messages. Help!
When this happens, you would see an output similar to this.
info: PlayfabMultiplayerAgent[0]
Waiting for heartbeats from the game server.....
info: PlayfabMultiplayerAgent[0]
Container 4179fa451214251a45d1a8e8338203a9ff05dc6ec1231c50e1f81f5508b3e1c8 exited with exit code 1.
info: PlayfabMultiplayerAgent[0]
Collecting logs for container 4179fa451214251a45d1a8e8338203a9ff05dc6ec1231c50e1f81f5508b3e1c8.
info: PlayfabMultiplayerAgent[0]
Copying log file
C:\ProgramData\Docker\containers\4179fa451214251a45d1a8e8338203a9ff05dc6ec1231c50e1f81f5508b3e1c8\4179fa4512
14251a45d1a8e8338203a9ff05dc6ec1231c50e1f81f5508b3e1c8-json.log for container
4179fa451214251a45d1a8e8338203a9ff05dc6ec1231c50e1f81f5508b3e1c8 to D:\playfab\PlayFabVmAgentOutput\2020-09-
29T01-42-01\GameLogs\032e7357-1956-4a60-9682-ca462cc3ea12\PF_ConsoleLogs.txt.
info: PlayfabMultiplayerAgent[0]
Deleting container 4179fa451214251a45d1a8e8338203a9ff05dc6ec1231c50e1f81f5508b3e1c8.

Debugging steps
Check PF_ConsoleLogs.txt for any useful error message
Check if your .zip asset package contains all the required DLLs for your game. For instructions, see
Determining required DLLs.
Check the Windows Event log to see if there's any useful information about Docker failures
On LocalMultiplayerAgent, I am not getting any heartbeats
There might be some leftover containers from previous attempts. You can use docker ps -a to see all
containers and docker rm -f <containerNameOrTag> to delete them.
On Windows, how can I monitor TCP and UDP packets?
Consider using a tool like Wireshark (external link) utility.
How can I debug a deployed multiplayer server using Visual Studio?
For instructions, see Using Visual Studio to debug servers

See also
Locally debugging game servers
Locally debugging game servers and integration
with PlayFab
5/24/2022 • 9 minutes to read • Edit Online

Overview
PlayFab multiplayer game servers require integration with PlayFab Game Server SDK (GSDK). In addition, game
servers are run as containerized applications on the PlayFab Multiplayer platform.
Running them as containerized applications enables running and debugging the server locally, in an
environment that matches that of the PlayFab platform in Azure. This facilitates faster development iterations.
This article helps you verify that your PlayFab game server conforms to the platform requirements.
The PlayFab local debugging toolset includes LocalMultiplayerAgent that provides mock responses to the GSDK
and verifies whether your game server is integrated with the GSDK correctly. With the mock responses, the
VmAgent cycles the game server through various states in its lifecycle on the PlayFab Multiplayer platform.
You can configure the agent to run the game server as a containerized application and verify that your game
server is packaged with all the required dependencies and will run without issues on the PlayFab Multiplayer
platform. LocalMultiplayerAgent can work with either Windows or Linux game servers.

Basic Setup - Windows


Integrate your game server with the GSDK and build it. For more information, see Integrating game
servers with the PlayFab Game Server SDK (GSDK).
Compress your game server and its dependencies to a zip archive. To run properly in container mode, the
zip archive must contain any system DLLs that are not included in the container image. For more
information, see determine required system DLLs..

NOTE
Avoid this common mistake - do not accidentally zip a folder within a folder in the zip. After zipping, browse the
zip folder and double-check that your compression software did not add an extra layer of file hierarchy.

Download the local debugging toolset and extract it to a folder of your choice (such as
C:\PlayFabVmAgent).
While inspecting the: LocalMultiplayerAgent MultiplayerSettings.json Generator json file, read more
about the following options below.
Navigate to the location of the extracted folder and open the MultiplayerSettings.json file in a text editor
(such as Visual Studio Code). Update the following properties:
LocalFilePath - Full Local Path (on your workstation) to the game server asset zip file created earlier,
for example: D:\\MyAmazingGame\\asset.zip (note that backslashes need to be escaped for JSON
formatting).
StartGameCommand - The full path to the game server executable within the container. For example, if
the name of the executable is mygame.exe, a sample path would be C:\\Assets\\mygame.exe. The
paths for the StartGameCommand are different for a Process and a Container. The
StartGameCommand path for a container is an absolute path to a resource in the container or asset
folder. The StartGameCommand path for a process is a relative path where the working directory will
be the first asset specified.
PortMappingsList - These are the ports that are available to your game while running. NodePort is the
port that is opened on your workstation, GamePort.Number is the port that your game server needs to
bind to when running in a container. Update the GamePort section to match the protocol and port at
which your game server is listening for clients. If your game server needs multiple ports, copy/paste
the existing port configuration and increment NodePort then update GamePort.Number and
GamePort.Name to the required port. When running as a process, GamePort.Number is ignored, your
process should bind to NodePort. To handle both cases, do one of the following:
Set the ports to the same value
Check the GSDK config at runtime for the value with the key GamePort.Name which always
returns the correct port to bind against.
There are additional fields in the MultiplayerSettings.json file you might want to edit:
ResourceLimits (optional) - If specified, docker limits CPU/memory usage. Warning: If your server
goes over the allowed memory, it is killed. ResourceLimits can only be specified in container mode.
SessionCookie (optional) - Any session cookie that is passed to your game server as part of the
RequestMultiplayerServer API call.
OutputFolder (optional) - Path to a drive or folder where the outputs and config files are generated.
Ensure that there is sufficient space available since the game server will be extracted under this path. If
not specified, the agent folder is used.
MountPath - The path within the container at which to mount the asset. This field does not need to be
specified when running in process mode. We recommend using the sample value - C:\\Assets (note
that backslashes need to be escaped for JSON formatting).
AgentListeningPort - Specifies the port to which the agent binds to communicate with the game
server. Any open port will work, if you have another process binding to 56001 you must change this
value (or kill the other process).

Verifying GSDK integration


In the MultiplayerSettings.json file, set RunContainer to false .
In a Powershell window (as Administrator):
Change your working directory to the folder where the toolset was extracted.
Run LocalMultiplayerAgent.exe. At this point, LocalMultiplayerAgent sets up the http listener, unzips
the game asset, and starts the game server in a separate process. LocalMultiplayerAgent then waits
for heartbeats from the GSDK integrated with your game server.
If the GSDK is integrated correctly, LocalMultiplayerAgent prints the following outputs:
CurrentGameState - Initializing (this is optional and may not show up if your game server directly
calls GSDK::ReadyForPlayers and does not call GSDK::Start )
CurrentGameState - StandingBy
CurrentGameState - Active
CurrentGameState - Terminating
If the shutdown callbacks are set up correctly, your game server exits soon after the state is set to
terminating. It is important to verify that the game server exits to avoid ungraceful shutdowns on the PlayFab
platform.
The LocalMultiplayerAgent should also terminate along with the game.
Testing connection to your game
When your game server executable is running and LocalMultiplayerAgent prints CurrentGameState - Active ,
you can connect to your game server using IP address 127.0.0.1 and port NodePort on which your game
server is listening.
After NumHeartBeatsForActivateResponse heartbeats, LocalMultiplayerAgent requests the game server to
move from standby to active. Then after NumHeartBeatsForTerminateResponse heartbeats
LocalMultiplayerAgent requests the game server to move from active to terminated. This behavior can be
tuned by updating the values in the MultiplayerSettings.json file.

Verifying containerization
If you are new to the container world, you can check an intro here.
Prerequisites
Windows 10 Pro (or above) with April 2018 (1803) update.
Download Docker. Alternately, you can download it from the main page of the Docker website.
Setup
Ensure that Docker is set to use Windows Containers
In a Powershell window (as Administrator):
Navigate to the folder where the toolset was extracted.
Run Setup.ps1 which sets up the docker networks, add firewall rules to communicate with
LocalMultiplayerAgent , and pull down the PlayFab docker image from Microsoft/PlayFab-
Multiplayer. Note that the first time the script runs, it can take a few minutes to download the
container image.

NOTE
To run this setup successfully, you may have to configure the firewall of any 3rd party antivirus program
(such as McAfee, Norton, or Avira) that you have installed.

Running the game server within a container


In the MultiplayerSettings.json file, set RunContainer to true .
Open a Powershell window (as Administrator) in the folder where the toolset was extracted
(C:\PlayFabVmAgent) and run LocalMultiplayerAgent.exe . This starts the game server within a container.
Eventually, you should see game state change output in the Powershell window ( just like in the Verifying
GSDK integration section above).
Testing connection to your game server running within a container
When LocalMultiplayerAgent output prints CurrentGameState - Active , connect to your game server using IP
address 127.0.0.1 and port equal to NodePort (by default 56100 ) that's specified in the
MultiplayerSettings.json file.
After NumHeartBeatsForActivateResponse heartbeats, LocalMultiplayerAgent requests the game server to
move from standby to active. Then after NumHeartBeatsForTerminateResponse heartbeats
LocalMultiplayerAgent requests the game server to move from active to terminated. This behavior can be
tuned by updating the values in the MultiplayerSettings.json file.
Using LocalMultiplayerAgent with Linux Containers
You can use LocalMultiplayerAgent to debug your Linux game server by running it on a container in Windows
using Docker for Windows. You can see more information about running Linux containers on Windows here. In
essense, all you need to is run the agent with the -lcow parameter as well as properly configure your
LocalMultiplayerSettings.json file.
To run your containerized Linux game servers on Windows, you'll need to perform the following steps:
Download latest version of LocalMultiplayerAgent from the Releases page on GitHub
Install Docker Desktop on Windows
Make sure it's running on Linux Containers
You should mount one of your hard drives, you can find instructions here
Your game server image can be published on a container registry or can be locally built.
You should run SetupLinuxContainersOnWindows.ps1 Powershell file which will create a Docker network called
"PlayFab"
You should properly configure your LocalMultiplayerSettings.json file. Below you can see a sample, included
in MultiplayerSettingsLinuxContainersOnWindowsSample.json :

{
"RunContainer": true,
"OutputFolder": "C:\\output\\UnityServerLinux",
"NumHeartBeatsForActivateResponse": 10,
"NumHeartBeatsForTerminateResponse": 60,
"TitleId": "",
"BuildId": "00000000-0000-0000-0000-000000000000",
"Region": "WestUs",
"AgentListeningPort": 56001,
"ContainerStartParameters": {
"ImageDetails": {
"Registry": "mydockerregistry.io",
"ImageName": "mygame",
"ImageTag": "0.1",
"Username": "",
"Password": ""
}
},
"PortMappingsList": [
[
{
"NodePort": 56100,
"GamePort": {
"Name": "game_port",
"Number": 7777,
"Protocol": "TCP"
}
}
]
],
"SessionConfig": {
"SessionId": "ba67d671-512a-4e7d-a38c-2329ce181946",
"SessionCookie": null,
"InitialPlayers": [ "Player1", "Player2" ]
}
}

Some notes:
1. You must set RunContainer to true. This is required for Linux game servers.
2. Modify imageDetails with your game server docker image details. Image may be built locally (using
docker build command) or be hosted in a remote container registry.
3. StartGameCommand and AssetDetails are optional. You don't normally use them when you use a Docker
container since all game assets + start game server command can be packaged in the corresponding
Dockerfile
4. Last, but definitely not least, pay attention to the casing on your OutputFolder variable, since Linux
containers are case sensitive. If casing is wrong, you might see a Docker exception similar to error while
creating mount source path '/host_mnt/c/output/UnityServerLinux/PlayFabVmAgentOutput/2020-01-
30T12-47-09/GameLogs/a94cfbb5-95a4-480f-a4af-749c2d9cf04b': mkdir /host_mnt/c/output: file exists
After you perform all the previous steps, you can then run the LocalMultiPlayerAgent with the command
LocalMultiplayerAgent.exe -lcow (lcow stands for Linux Containers On Windows)

Troubleshooting
In container mode, if your game server exits immediately with an error similar to "Container ... exited with
exit code 1", but it works fine in process mode, make sure that you have included all required system DLLs in
your asset package.
All logs are located under OutputFolder that is specified in the MultiplayerSettings.json file.
LocalMultiplayerAgent creates a new folder each time it is started, with the timestamp as folder name. All
game server logs emitted via GSDK are located within the GameLogs folder.
If the game server is running in a container, there might be an additional level of directory hierarchy to sift
through.
The GSDK writes debug logs to the GameLogs folder. These logs are located within the GameLogs folder
along with the logs output by the game server.
Ensure firewalls (windows and other anti-virus) are configured to allow the traffic over the ports.
If you get an error similar to:
Docker API responded with status code=InternalServerError, response={"message":"failed to create endpoint
<container_name> on network playfab: hnsCall failed in Win32: The specified port already exists". It is
likely there is already a container running on the specified port.
This can happen if LocalMultiplayerAgent exits prematurely. Use the command docker ps to find the
container that is running, and then kill it using docker kill <container_name> .
If you get an error that contains Failed to find network 'playfab' . Try rerunning Setup.ps1
Known Limitations
1. Containers might not terminate at the end of the debugging. If this occurs, run the following PowerShell
commands as Administrator. These commands stop and remove all containers, including those were not
started by LocalMultiplayerAgent .

docker stop $(docker ps -aq)


docker rm $(docker ps -aq)
Enable automatic crash dump collection
5/24/2022 • 2 minutes to read • Edit Online

This article will cover how to enable automatic crash dump collection for servers. We currently don't support
this feature in the UI or through PowerShell.

NOTE
This functionality is only available for windows container servers. We do not currently have a way for linux or Windows
process based servers.

To enable automatic crash dump collection, you can use CreateBuildWithManagedContainer api as shown below.
To learn more about the CreateBuildwithManagedContainer see Multiplayer Server - CreateBuild With Managed
Container In the JSON, you can add in a new field called "WindowsCrashDumpConfiguration" to the request
body that will enable crash dumps.

"BuildName": "crashDumpTest",
"ContainerFlavor": "ManagedWindowsServerCore",
"MultiplayerServerCountPerVm": 1,
"Ports": [
{
"Name": "PortName",
"Num": 1243,
"Protocol": "TCP"
}
],
"RegionConfigurations": [
{
"Region": "EastUs",
"MaxServers": 1,
"StandbyServers": 1
}
],
"StartMultiplayerServerCommand": "C:\\Assets\\CrashingServerExample.exe sizeMiB:10",
"UseStreamingForAssetDownloads": false,
"GameAssetReferences": [
{
"FileName": "CrashingServerExample_v1_0.zip",
"MountPath": "C:\\Assets"
}
],
"VmSize": "Standard_D2_v2",
"WindowsCrashDumpConfiguration": {
"IsEnabled": true,
"DumpType": 0,
"CustomDumpFlags": 6693
}
}

NOTE
Once you enable this your DumpType and CustomDumpFlag values will get put into the registry keys. To learn more read
Collecting User mode dumps

Once a server has crashed and logs have been created a PlayStream notification will give you a server ID. After
you get the server ID, you can search for it under the archived servers page. Navigate to the Archived servers
page and paste into the search bar the server ID you were given. Download the logs for the affected server and
you'll see your crash dump files. To learn more, read Archiving and retrieving multiplayer server logs
Attaching a Profiler
5/24/2022 • 2 minutes to read • Edit Online

This article goes over attaching a profiler and how you can get the output files. A profiler is used to help debug
issues around graphics and performance of your game servers. To use tools such as dotnet trace or PIX you'll
need to first upload your profiler of choice. Then you'll associate it to a build, and the output files will be put into
your logs folder.
It isn't recommended to attach a profiler to production builds as it can affect performance. Set up for attaching a
profiler will need to be done at build creation. We currently don't support attaching a profiler through Game
Manager so you'll need to create a build using our APIs. For more information, see Walkthrough: Deploy builds
using PowerShell/API.
When creating a build, there's a field for asset reference under the monitoring configuration. Include the asset
reference in the monitoring configuration. Ensure your asset is uploaded in Game Manager. To learn more, see
Manage assets in Build Overview.
For a Linux server, below is a sample of an execution script for the profiler.

sighdl()
{
#This is the folder the monitoring output should be written to.
monitoring_folder_path = "${PF_MONITORING_LOG_FOLDER}"

#Code to end monitoring and copy the output

exit 0
}

#set up the trap function to catch the signals and exit gracefully
trap sighdl SIGKILL SIGINT SIGTERM
sleep 3600

For a windows server below is a sample of an execution script for the profiler.

#Sample function that checks for the sentinel file's existence in order to end.
function Check_Sentinel_File()
{
$fullPath = $Env:PF_SENTINEL_FILE
while(!(Test-Path $fullPath)) { Start-Sleep 10}

#PF_MONITORING_LOG_FOLDER contains the log folder where the monitoring output should be saved

$outputPath = "{0}/{1}" -f $Env:PF_MONITORING_LOG_FOLDER, "output.txt"


"I've died!" | Out-File $outputPath
}

Check_Sentinel_File

Make sure you save your output inside the folder set on the PF_MONITORING_LOG_FOLDER
environment variable as it will ensure your output is saved.
Once the server has been archived, you can download the logs and inside you'll find a folder called
PlayfabProfilingOutput . This will have what you have written in your execution script along with any
standard outputs and errors.
Scaling Standby
5/24/2022 • 4 minutes to read • Edit Online

PlayFab’s scaling capabilities enable developers to adjust game server hosting capacity to meet actual player
demand. These controls help developers efficiently keep game server hosting costs low while maintaining
enough capacity to quickly add new players to join multiplayer games with minimal to no waiting.
Scaling game servers is something developers think about after their game is successfully deployed and
operating. The controls demonstrated in this section helps developers define the elasticity of resource scaling
while maintaining enough capacity to add new players with minimal to no waiting.
Servers in the propping and standing-by states are billed to your title, and you'll want to optimize these
processes to reduce cost. Before we get to how you can calculate the standing by target here are some helpful
terms to understand.

Terminology
Terms you should understand about scaling standby servers.
Target Standby – Also commonly known as Standby Target and Standing by target, it is a value set by the
platform that specifies the target number of standby servers to have available to avoid standby pool
starvation.
Target Standby Floor – A game developer configurable measure representing the minimum floor quantity
of servers kept idle to fulfill demand for new game servers.
Actual Standby – The quantity of standby servers reported by the Multiplayer Servers platform where its
values are distinct between when Dynamic Standby is enabled versus when Dynamic Standby is disabled.
Pre-propping - Azure and PlayFab must create the virtual machine, initialize its operating system, and
configure its environment. PlayFab drives this pre-propping activity before the virtual machine is assigned to
a customer and billed.
Propping - The game servers assets must be loaded, and the game server application itself often needs
some time to prepare for players.
Standing by In order to immediately fulfill demand for a multiplayer server, some servers are kept idle
ready for players constantly.

Configuring target standby


You configure standing-by targets on a per build and per region basis. Typically you should set the standing-by
level proportionally to the propping time and target allocation rate: Standing by Target = (Propping Time +
Ser ver time to standing by) * Target Allocation Rate
For example, if a Linux server that takes 100 seconds to prop, and a game that is expected to have up to one
server allocated every 5 seconds (0.2 servers/second). A standing by pool of 100 * 0.2 = 20 servers will stably
support this build. After 100 seconds, 20 servers will be expended but there will have been time to build another
20.
When calling the RequestMultiplayerServer API, it's important to indicate all of the regions that are acceptable to
the player experience. If region #1 doesn't have a standing by server available, then region #2 will be requested
and will continue for as many regions as you've configured.

Scaling benefits
A summary of scaling benefits includes:

B EN EF IT DESC RIP T IO N

Increase application availability Ensures that your game server pool always has the right
number of VMs by proactively provisioning capacity

Lower compute costs Adds instances only when needed to optimize costs

Scale instances across purchase options Scaling options optimize performance across instance type,
region, size and game server build configurations

Scaling methods
PlayFab offers multiple mechanisms to scale when and how to scale your servers. Game developers have the
flexibility of:
1. Configuring minimum & maximum thresholds
2. Customizing scale configurations per server build profiles such as (a) instance types, (b) VM size, or (c)
regions
3. Managing change effortlessly from the developers’ portal or from the Multiplayer Servers RESTful API
4. Monitor scaling metrics in server & usage charts
The three methods to configure scaling of game servers are:
Default
Scheduled
Dynamic
Each has a unique approach but trigger from a known or unknown state of player demand. The default method
scales up to the max servers configured and scales down on sessions completed. In this mechanism, there’s no
extra steps required by the developer. This is the simplest method where developers set a max server and
standby limit so that PlayFab automatically shrinks and grows VMs by way of player demand.

C O N T RO L S P L AY ER DEM A N D A P P RO A C H USE C A SE Y IEL D

Default Unpredictable Automatic Normal game Won't scale fast


operation enough for spikes in
traffic

Scheduled Predictable Planned Planned event launch Track schedule


changes for shifts in
player demand

Dynamic Unpredictable Formulative Sudden traffic spike

To fully embrace the breadth of scaling options, the following key concepts and terminology must be
understood first.
Key Concepts
Scaling mechanisms control the number of standby server availability
Standby servers are VM allocated servers with no active connected players. These will transition in accepting
for player connections in response to RequestMultiplayerServer API call; they transition to a termination state
when the game server process exits
Scaling mechanisms are uniquely applied at each region of a build
Each scaling configuration is represented as a region override

Standby pool starvation


PlayFab’s Multiplayer Servers provides a bank of standby servers. This helps to support immediate fulfillment of
requests for more game servers in response to player demand. If the demand for extra servers grows faster
than the time necessary to acquire and provision servers from the reserves, the pool of standby servers
becomes depleted. The pool of available servers enters a “starvation” state and requests for game servers fail
until more servers can be provisioned. The schedule standby and dynamic standby scaling methods
automatically activate increased provisioning of game servers to meet player demand.
Dynamic Standby
5/24/2022 • 4 minutes to read • Edit Online

Dynamic Standby is an auto scaling enhancement that monitors standby server threshold levels and
dynamically activates increased provisioning of game servers to meet demand at scale.
Dynamic Scaling enables you to follow the demand curve for your player traffic, reducing the need to manually
provision multiplayer server capacity in advance. For example, you can set thresholds to multiply standby
servers by amounts when standby servers deplete to percentage of “standby available”.

Terminology
Dynamic Standby Settings – A game developer configurable programmatic object representing Dynamic
Standby settings to avoid standby pool starvation.
Dynamic Standby Activated – The point in time when the Multiplayer Servers platform starts allocating
standby servers at a rate aligned with the dynamic Standby settings, overriding that target standby floor
settings.
Dynamic Standby Deactivated – The point in time when the Multiplayer Servers platform stops allocating
standby servers at a rate aligned with the dynamic Standby settings, restoring the target standby floor
settings.

How it works
Game developers specify a target standby floor value for the minimum number of standby servers. If the rate at
which active servers are allocated grows rapidly, the actual standby servers may hit zero. If Dynamic Standby is
enabled, an auto scaling heuristic will trigger and adjust the target standby value used by the platform to
compensate for the rate of active server allocations.
To state this another way, if the number of available standby servers decreases at a rate that could lead to
standby pool starvation, dynamic standby will increase the target number standby servers.
The following graphs show the difference of availability of servers when Dynamic Standby is enabled and when
it is disabled.

C H A RT L EGEN D

At time T2, even though the target standby floor setting is 10, the actual standby value reported by the platform
is near zero because the rate at which active servers are allocated is too large for the number of standby servers.
With Dynamic Standby enabled, the target standby is set to 20. This allows the standby pool to handle the
request rate and rebuild to handle the additional growth in active servers.
Calculating Dynamic Standby Targets
With Dynamic Standby enabled, the target standby is calculated for each threshold configured:
IF (Active Servers > 1X Target Standby) AND ((Actual Standby / Target Standby Floor) < 0.50) THEN Target
Standby = 1.5 * Target Standby
IF (Active Servers > 1X Target Standby) AND ((Actual Standby / Target Standby Floor) < 0.25) THEN Target
Standby = 3.0 * Target Standby
IF (Active Servers > 1X Target Standby) AND ((Actual Standby / Target Standby Floor) < 0.005) THEN Target
Standby = 4.0 * Target Standby
Revisiting figure #1 above, the following table illustrates the target standby calculation inputs and its values:

A C T IVE SERVER
A C T IVE SERVER A L LO C AT IO N TA RGET A C T UA L TA RGET
T IM E C O UN T RAT E STA N DB Y F LO O R STA N DB Y STA N DB Y

T0 40 >+40 servers 10 10 10
per time T

T1 20 -20 servers per 10 10 10


time T

T2 30 +10 servers per 10 4 35


time T

T3 50 +10 servers per 10 1 40


time T

T4 70 +20 servers per 10 4 40


time T

T5 80 +10 servers per 10 10 40


time T

T6 50 -30 servers per 10 10 10


time T

When Dynamic Standby is deactivated, there is a gradual ramp down of standby servers until the original
standby floor is reached.

Dynamic Standby User Interface


The Dynamic Standby feature can be enabled from the developer portal by navigating to the Multiplayer |
Servers | Build Regions page. Dynamic Standby settings are uniquely applied to each region of a build. When
enabled, the Build Servers by Region table presents a lightning bolt next to the region name
To enable Dynamic Standby, create a region overrides by selecting Edit overrides to configure scaling settings for
a specific region.

When the dynamic standby button is toggled in the on position, the dynamic overrides dialog expands to with
configuration options. The options control how Dynamic Standby responds when it ramps up or down due to
player demand. Each dialog input is described in the table below:

DIA LO G IN P UT DESC RIP T IO N

Standby servers The target number of servers to have waiting for an


allocation before applying dynamic standby

Maximum servers The maximum number of servers that will be started


including servers in all states

Ramp down time The amount of time after a threshold is no longer triggered
before the target standby will be reduced to the normal level

Dynamic Activation Thresholds The thresholds at which to trigger dynamic standby

Percent Standby The threshold triggered when current standby drops to this
percentage of the base target standby

Multiply by The target standby will be multiplied by this amount while


the threshold is reached
After making changes to the dynamic overrides of a region, select Save and close to save the changes made and
return to the build regions summary page. The builds region summary page indicate that Dynamic standby is
enabled and briefly summarize the threshold settings.
Scheduled Standby
5/24/2022 • 2 minutes to read • Edit Online

Scheduled Standby is an auto scaling enhancement that adjusts standby server levels at a single or recurring
scheduled date & time. Scheduled standby enables server scaling based on a schedule. It allows you to scale
your game server ahead of predicted load changes. For example, every weekend, traffic to your game server
increases on Friday 2 PM PST and starts to decrease by Sunday 11 PM PST. You can plan your scaling activities
based on the known player demand patterns of your game.

How it works
Game developers specify a target standby floor value for the minimum number of standby servers. If player
demand is predicted to grow during a specific date & time window where active servers grows rapidly, the
actual standby servers may hit zero triggering standby pool starvation. If Scheduled Standby is enabled, standby
pools can auto scale and adjust the target standby value used by the platform at a specific date and time.

Scheduled Standby User Interface


The Scheduled Standby feature can be enabled from the developer portal by navigating to the Multiplayer |
Servers | Build Regions page. Scheduled Standby settings are uniquely applied to each region of a build. When
enabled, the Build Servers by Region table presents a clock ( ) next to the region name

To enable Scheduled Standby, create a region overrides by selecting Edit overrides to configure scaling settings
for a specific region.

Configuring a regions override will surface options to enable server scaling settings for both dynamic standby
and scheduled standby. Scheduled standby is disabled by default. To enable scheduled standby, select New
override in the Scheduled overrides page section.
When the scheduled new override is selected, , the scheduled overrides dialog expands to surface options that
control how Scheduled Standby behaves when it ramps up to support player demand or when it ramps down
when players disconnect from active servers. Each dialog input is described below:

DIA LO G IN P UT DESC RIP T IO N

Target standby The target number of servers to have waiting for an


allocation before applying dynamic standby

Description Description of the scheduled override

Day of the week Scheduled day of the week to scale standby settings

Duration Scheduled length of time to maintain the scale of standby


settings

Begin schedule Scheduled date to activate the scheduled overrides

Repeat weekly Flag determining if scheduled standby settings will repeat on


the day of the week specified
Scheduled standby supports multiple scheduled overrides providing the schedules don't overlap each other.
Simply select New override to add another scheduled override. A scheduled override can also be disabled in the
override details page section.

After making changes to the scheduled overrides of a region, select Save and close to save the changes made
and return to the build regions summary page. The builds region summary page indicate that Scheduled
standby is enabled and tabulates the scheduled settings.
Scaling Programmatically
5/24/2022 • 2 minutes to read • Edit Online

Dynamic Standby Object


The Dynamic Standby feature introduces a new object to the Multiplayer programming interface called
DynamicStandby . The Dynamic Standby object is an optional property of the BuildRegionParams object.

Configuring Dynamic Standby requires editing the settings properties of the Dynamic Standby object. Modifying
the default values of the properties is an advanced game server feature and must be done with caution.

Scheduled Standby Object


The Scheduled Standby feature introduces a new object to the Multiplayer programming interface called
ScheduledStandby . The Scheduled Standby object is an optional property of the BuildRegionParams object.

Configuring Schedule Standby requires editing the settings properties of the Schedule Standby object.
Modifying the default values of the properties is an advanced game server feature and must be done with
caution.

Enable Standby Scaling programmatically


You can programmatically enable Dynamic or Scheduled Standby by calling any of the following Multiplayer
Server APIs:
1. Override Update Build Regions
UPSERT: An operation that inserts rows into a database table (if they do not already exist) or updates them (if
they do).
2. Create Build with Custom Container
3. Create Build with Managed Container
To enable Dynamic or Schedule Standby programmatically, toggle the Mode property to ON. The Mode is the
only required property of the Dynamic Standby or Schedule Standby Settings object. Its default value is OFF .
Using Quality-of-Service (QoS) beacons to measure
player latency to Azure
5/24/2022 • 3 minutes to read • Edit Online

You can deploy PlayFab multiplayer servers to more than a dozen Azure regions. There are two reasons to do
this:
1. Additional regions provide redundancy. If a single Azure region fails, players can access servers in other
regions.
2. Additional regions allow players to access servers that are "nearby" and deliver low-latency connectivity.
When you call RequestMultiplayerServer, you specify a ranked list of Azure regions that PlayFab uses to fulfill
the request. PlayFab will attempt to fulfill the request using the #1 ranked region, but if there aren't servers
standing by in that region, or the region has some other fault, a sub-optimal region further down the list will be
attempted.
Whenever possible, you should use player latency data to inform the ranking of Azure regions used while
requesting a multiplayer server. PlayFab provides services and tools to help with this task.

Quality-of-service beacons
PlayFab operates beacons in every Azure region in use by PlayFab multiplayer servers. These beacons will reflect
UDP traffic and can be used to measure latency with UDP transport.
The usage of UDP is important, because most multiplayer games use UDP transport for their most
performance-critical game traffic. Internet service providers and other elements of the Internet ecosystem may
deliver differentiated performance for UDP vs. TCP vs. ICMP flows.
This is the typical flow for using these beacons in the context of a player device:
1. Login the player to PlayFab. This is typically done with a LoginWithCustomID or another login API.
2. Call ListQoSServersForTitle. This provides hostnames to PlayFab's QoS beacons. A typical implementation
might have this procedure occur on the Multiplayer Menu page for the game.
3. Create a UDP socket.
4. Send a single UDP datagram to port 3075 on the QoS server. The message content must start with 0xFFFF
(1111 1111 1111 1111).
5. The server will reply with a single datagram, with the message contents having the first 2 bytes "flipped" to
0x0000 (0000 0000 0000 0000). The rest of the datagram contents will be copied from the initial ping.
6. Measure the time between sending the UDP message and receiving a response.

Using the quality-of-service SDK


The PlayFab C# SDK and cross-platform (CPP) SDK provide an implementation of the QoS ping code. You can
build an SDK and use it as a helper library in your PC games, reference the C# NuGet package, or use the code
as an example for other platforms.
Each API returns a QosResult which contains a sorted list of regions along with the average ping time to each
region.
C#
There is a QoS APIs available in the C# SDK. A sample implementation, WindowsRunnerCSharpClient, is
available in the gsdkSamples repository.
The code is located in PlayFabQosApi.cs.
Parameters:
timeoutMs - The timeout (in milliseconds) applied to each ping attempt (Default: 250ms).
pingsPerRegion - The number of ping attempts to make against each region (Default: 10). Increasing this
number will increase execution time, but reduce the chance of inaccurate results.
degreeOfParallelism - The maximum number of pings to make in parallel (Default: 4). Increasing this
number will reduce execution time, but network contention can cause inaccurate results if this number is too
large.

public async Task<QosResult> GetQosResultAsync(


int timeoutMs = DefaultTimeoutMs,
int pingsPerRegion = DefaultPingsPerRegion,
int degreeOfParallelism = DefaultDegreeOfParallelism)
{

C++
There are the two QoS APIs available in the PlayFab cross-platform (CPP) SDK.
The code is located in PlayFabQosApi.cpp.
Parameters:
numThreads - The maximum number of pings to make in parallel. Increasing this number will reduce
execution time, but network contention can cause inaccurate results if this number is too big.
timeoutMs - The timeout (in milliseconds) applied to each ping attempt (Default: 250ms).

// Runs a QoS operation asynchronously. The operation pings a set of datacenters and returns a result with
average response times.
std::future<QoSResult> GetQoSResultAsync(unsigned int numThreads, unsigned int timeoutMs =
DEFAULT_TIMEOUT_MS);

// Runs a QoS operation synchronously. The operation pings a set of datacenters and returns a result with
average response times.
QoSResult GetQoSResult(unsigned int numThreads, unsigned int timeoutMs = DEFAULT_TIMEOUT_MS);
Allocating game servers and connecting Visual
Studio debugging tools
5/24/2022 • 3 minutes to read • Edit Online

Allocating multiplayer sessions


With PlayFab multiplayer servers 2.0, you can allocate instances of your multiplayer server application using the
RequestMultiplayerServer API.
Typically this API is called from your own services (perhaps a matchmaking service or lobby service), using a
PlayFab Developer Secret Key configured for the specific title. For more information about secret keys, see
Secret key management.
A typical pattern for bringing players together and allocating servers:
1. Clients collect network QoS information.
2. Clients interact with a custom matchmaking service, or assemble via social invitations.
3. A custom matchmaking service allocates a session for the group, using a prioritized list of regions.
RequestMultiplayerSer ver has several key parameters:
BuildID - The specific server build to be allocated.
SessionID - An identifier for the session. This is a GUID string generated by the caller. Retries to this API for
the same logical session should re-use the same identifier. This mitigates the possibility of caller retry
behavior creating unnecessary servers.
SessionCookie - Arbitrary data that will be communicated via the game server SDK to the allocated session
at activation. A typical usage of this field is communicating a shared key that game servers use to
authenticate clients. Data must be smaller than 4 kilobytes.
PreferredRegions - An ordered list of regions used to allocate servers. We recommend using network QoS
measurements collected from the client devices as the primary factor for ranking regions.
A successful allocation will return the following information:
The IPv4 address of the server.
The TCP/UDP port mappings (see Connecting Clients to game servers).
The Region of the server.

NOTE
You can use the MpsAllocatorSample (found here) for an easy way to allocate game servers during development of your
game

Client allocation
Multiplayer servers are expensive and powerful. By default, you can only request a multiplayer server from your
own trusted service using a PlayFab developer secret key.
However, allocating servers directly from player devices can save you the cost of implementing service-to-
service calls and be useful in some circumstances.
To enable client allocation:
Select Settings from the menu on the left.
Select the API Features tab.
Then activate the Allow Client to star t games option.

When this setting is activated, you can call RequestMultiplayerServer using the entity token for any player
associated with the title.

Debugging a deployed multiplayer server


You may want to remotely debug a game server while it is deployed in Azure. With Visual Studio, this currently
requires you to install and configure the Visual Studio Remote Debugging tools in the container.

NOTE
The procedure that follows will enable insecure, unauthenticated debugging.

The following procedure should only be applied to server builds that are for development and testing, and
generally avoided in a player-facing environment.
1. Get the VS2017 Remote Debugging tools:

Invoke-WebRequest -OutFile rtools_setup_x64.exe -Uri


https://aka.ms/vs/15/release/RemoteTools.amd64ret.enu.exe

2. Include these tools in your game server asset package.


3. As part of creating your server build in Game Manager or with the Entity API, configure port 4022 TCP as a
debug port.
4. You will need to run msvsmon within the container, to enable remote debugging. A common pattern is to
specify a CMD script as the Game Start command, and to use a command-line argument to launch msvsmon
in addition to your game server executable.
5. Execute msvsmon once with:

/prepcomputer /quiet

6. Execute msvsmon with flags (shown below).

/nostatus /noauth /nosecuritywarn /anyuser /nofirewallwarn /nodiscovery /port 4022

NOTE
We recommend specifically listing the port so your program can handle the process exit code if the port is already in use,
rather than binding to a random port which isn't open.

7. Allocate your game server.


8. Attempt to debug via VS, using the external debug port returned from the allocate call.
Connecting clients to game servers
5/24/2022 • 2 minutes to read • Edit Online

PlayFab game servers are containerized applications. When game servers are deployed to Azure, their
networking environment is virtualized, and the game server will not have direct access to its Internet accessible
IP addresses.
Instead, game servers using GetAdaptersInfo (Windows) or GetIfAddrs (Linux) will observe a single network
adapter with non-unique IP addresses that have been configured through Network Address Translation (NAT44).
This usage of network virtualization and NAT allows game servers to maintain connections even as underlying
Azure infrastructure may be changing. All game servers have IPv4 connectivity, but IPv6 connectivity will be
added in the future.

NOTE
All Game Servers have IPv4 connectivity - IPv6 connectivity will be added in the future.

You may configure a Server deployment to pack multiple Game Server instances on a single virtual machine.
For the most part, this does not modify the network environment, as each containerization allows each Game
Server instance to have independent IP addresses and TCP/UDP port spaces.
However, all instances on a single virtual machine share the physical network infrastructure, and can create
network contention.
While testing high-density configurations, it is important to test that typical contention does not cause
unacceptable game play issues.
Different virtual machine sizes and operating systems are provisioned with differing levels of bandwidth. To see
the bandwidth provisioned for a specific SKU, please see Azure’s throughput documentation.
Game servers are allocated through service-to-service calls through the PlayFab server API. The connection
information required for client connectivity is passed through these services and clients, which typically use TCP
or UDP sockets to drive a direct connection to the game server. Typically, game servers will listen on well-known
UDP and TCP ports selected by the game developer.
Game clients need the Internet-facing IP address of your game servers to connect to them. Clients also need
port-forwarding information to allow well-known ports to which the server is listening, to be addressable
through the Azure network virtualization apparatus.

Public IPv4 Address


A mapping of developer-provided ports (by name) to the Internet-facing port.

GA M E SERVER P ROTO C O L N A M E P ROTO C O L IN T ERN ET - FA C IN G P O RT

Multiplayer UDP 3098

Debugger TCP 23222

Enabling TCP/UDP ports for game servers


The port requirements provided through Game Manager or the Entity API CreateBuild enables game clients to
contact the virtual machine. It also configures the firewall on the resident operating system to enable network
traffic on the ports you specify.

Public Internet-facing ports and IP addresses used by multiplayer


servers
The IP addresses used by the multiplayer VMs are drawn from the general pool of IP addresses used by Azure
VMs. These IPs are specified as the AzureCloud service tag. For more information, see [service tags on-
premises](https://docs.microsoft.com/ azure/virtual-network/service-tags-overview#service-tags-on-premises).
All VMs use a port range of 30000-31000 for game traffic and 50000-55000 for remote access (SSH/RDP)
traffic.
Managing Server Cores Quota
5/24/2022 • 2 minutes to read • Edit Online

Multiplayer Servers includes a free and limited capacity of simultaneous cores to evaluate the building of
multiplayer server games. Game developers enrolled in paid pricing plans, however, may request additional
server cores for their game title(s). Requesting additional quota will increase the maximum number of cores that
your multiplayer service has access to if the request is approved. The Multiplayer Ser vers | Quota
Summar y page presents a self-serve mechanism in Game Manager for game developers to:
Request additional quota
Review a histor y of quota requests provisioned or under review

Requesting additional quota


To request additional quota, access the Change Quota button on the Multiplayer Ser vers | Quota
Summar y page as shown in the screenshot below to request for additional quota. Changing your quota limit
will not increase your costs. Increased player activity results in more active servers. Active server usage and
costs will be reflected in your bill. Most requests will be immediately approved and provisioned. But some core
limit changes are subject to review and may require more information if your request exceeds what can be
provide at the time of the request.

How to request quota changes


1. Briefly describe the change requests. Examples include the name of your launch, event name or title game
mode.
2. Select the + Add change button to request a quota change as shown in the screenshot below. Quota
changes may include 1 or more changes to a VM family and region combination. Only VM family SKUs and
regions permitted in your pricing plan will surface in the options to choose from.
3. Apply a new core limit to adjust the quota to a VM family and region combination. The new core limit can be
any number between zero (0) and the desired quota for your title. A value of 0 indicates you are removing all
quota for the VM family SKU & region combination.
4. Select the +Add change button to specify a specific SKU and region combination of quota change requests
5. To delete a quota change before it is submitted, select the checkbox for that row and then Delete
6. After adding all SKU/region quota changes, select Submit to submit your quota change request.

7. After processing your request, if it is approved a notification will surface at the top of the Game Manager
indicating your request was approved. You may verify your changes were made by accessing the View Quota
page by selecting the View Quota button at the top of the Multiplayer Ser vers | Quota Summar y page.
8. If your request is too large to approve immediately, you will be prompted to provide additional details of
your quota change request as in (a) start date desired and (b) notes to help assess the change. Examples
include forecast title metrics (e.g. daily active users, concurrent game players per second, etc.). This
information will be manually reviewed by PlayFab who will be in contact with you regarding the status of
your quota change request.

Reviewing quota requests


To review a history of quota requests submitted for a title, access the Multiplayer Servers | Quota Summary
page and scroll to the Change History section on the page. This section tabularizes a history of requests
submitted and their current status.

There are only two statuses: Approved or In Review .


Change description provides a link to the quota change detail page. This page describes inputs submitted
at the time of the change request and a summary of the SKU & region selections associated with the quota
change
An image of the quota change detail is embedded below.
Accessing increased core limits and additional Azure
regions
5/24/2022 • 2 minutes to read • Edit Online

NOTE
This topic frequently references available Azure compute series and regions. To review PlayFab's current selection and
pricing see Multiplayer Servers - detailed price sheet.

Usage of PlayFab multiplayer servers has limits that are applied on a per-title basis. A key limit is the aggregate
number of Azure compute cores.
By default, indie, pro, and enterprise customers have limits set to 16 Av2 cores and 8 Dv2 cores split in East
US and West US.
Contact PlayFab Support to gain access to additional compute series, regions, or limit increases.
It is important to review title limits well in advance of any major game event, so you can be assured that PlayFab
will support peak player demand.

NOTE
For requests of 1,000 cores or more, it can take several days for PlayFab to secure the desired limit increases for you.

How to view and interpret multiplayer server limits


PlayFab measures your quota in cores :
6 F2_v2 vir tual machine consumes 12 Fv2 cores .
3 F4_v2 vir tual machines also consumes 12 cores .
The number of virtual machines does not matter, only the number of cores. Quota is specifically allocated for
each available compute series (A v2, D v2, D v3, F v1...) and region.
You can view the quota for a title on the Builds page by selecting View Quota in the top right.

NOTE
In the future, this will be integrated with the PlayFab limits page.
When you attempt to edit a build's regional configuration, PlayFab enforces that the maximum server
configuration you specify does not cause your title to exceed configured limits in aggregate.
The following screenshot of the Edit Build page shows these safeguards in action, as shown below.
You can use this page to specify the maximum number of multiplayer servers that a build can support in each
region. Depending on your virtual machine and density selections, a single server might require 1/4 of a Av2
core, or 4 Av2 cores.
In the above example there are 8 Av2 cores allocated to this title in West US. This build is configured to pack 3
servers on an single-core A1v2 virtual machine, so the configured "6 servers" maximum will consume 25% (2
cores) of the available 8 Av2 core quota in West US.
Azure Enterprise Agreement (EA) billing for PlayFab
services
5/24/2022 • 2 minutes to read • Edit Online

If you are interested in very high usage of PlayFab services ($500,000.00+ per year) including PlayFab
Essentials, Multiplayer Servers, Insights, Party, User Generated Content and Pub Sub, we may be able to bill you
through an Azure Enterprise Agreement (EA) . If you are an existing EA customer this requires Microsoft to
amend the terms of your EA to include PlayFab pricing details. If you are not an existing EA customer please
contact us at helloplayfab@microsoft.com to learn more about this billing option.
To start the EA billing process, contact your Azure solutions specialist and work with them to provide PlayFab
Sales:
Azure enterprise agreement (enrollment id) to govern PlayFab usage
Mapping of PlayFab Title IDs to Azure subscriptions for billing
PlayFab will emit multiplayer server consumption via an Azure SKU called PlayFab Multiplayer Servers. Each
PlayFab title will emit to the Azure subscription provided, and you will get a monthly bill through the EA portal.
This single Azure SKU for PlayFab Multiplayer Servers will be measured in dollars, without a break-down of cost
by resource (e.g. Fv2 compute, Zone 2 network egress, etc.). Use Game Manager to see a break-down of costs by
resource.
Billing for PlayFab Multiplayer Servers 2.0
5/24/2022 • 5 minutes to read • Edit Online

Most PlayFab services, including PlayFab Multiplayer Matchmaking, are included with every paid PlayFab pricing
mode, as part of our core offering. However, PlayFab Multiplayer Servers is billed on a consumption basis. This
document describes that billing plan.

What comes with your basic PlayFab Core Services package?


When MPS is enabled, you can use Multiplayer Servers for free in a limited capacity to evaluate the building of
multiplayer server games.

SERVIC E IN C L UDED F REE REGIO N

Dasv4 VM core hours 750 Dasv4 core hours East US

Dasv4 VM core hours 750 Dasv4 core hours North Europe

Network Egress 10 GB Zone 1

Network Egress 10 GB Zone 2

The free evaluation mode also includes limit imposed on simultaneous cores activated in game servers. The paid
modes, however, allow game developers to request additional server cores for their title.
The maximum simultaneous core quota in the free evaluation modes are:

SERVIC E IN C L UDED F REE REGIO N

Maximum Dasv4 cores 24 Dasv4 cores East US

Maximum Dasv4 cores 24 Dasv4 cores North Europe

This is typically not enough to launch a live game, but it can help you evaluate the service and get started.
To learn more about these different virtual machine please see Azure VM Sizes.

NOTE
The amount of free evaluation capacity provided per month is based on your PlayFab billing mode and is also calculated
based on core hours. This means that if you use a **single core ** Av2 series VM (like A1v2), you have 750 free hours. But
if you use a **dual core ** Av2 series VM (like A2v2), you have 375 free hours instead — 750 divided by 2 equals 375.

Consumption pricing for PlayFab Multiplayer Servers


Games that require Multiplayer Servers must purchase additional capacity through PlayFab's consumption
pricing plan. Below are the PlayFab resources that are used to bill for server utilization:
Vir tual machine instance hours - The hours of virtual machine time that your game servers are utilizing.
Different virtual machine and container selections are priced at different rates. See Multiplayer Servers
detailed price sheet for more information.
Network egress - The volume of data transmitted by your game servers to the Internet (in gigabytes).
Network egress is billed at different rates depending on the originating data center.
A typical monthly bill might be:

L IN E IT EM C O N SUM P T IO N UN IT RAT E SUB - TOTA L

Multiplayer Servers - 1000 VM Hours $0.252 $252.00


D2v2 - US East

Multiplayer Servers - 1000 VM Hours $0.252 $252.00


D2v2 - US South
Central

Multiplayer Servers - 1000 VM Hours $0.252 $252.00


D2v2 - US West

Multiplayer Servers - 1000 VM Hours $0.252 $252.00


D2v2 - West Europe

Multiplayer Servers - 100 VM Hours $0.302 $30.20


D2v2 - Australia East

Multiplayer Servers - 100 VM Hours $0.277 $27.70


D2v2 - East Asia

Multiplayer - Data 1000 GB $0.05 $50.00


Egress - Zone 1

Multiplayer - Data 100 GB $0.08 $8.00


Egress - Zone 2

Total $1,124.90

Estimating cost with an example


The primary inputs into your multiplayer server deployment are:
1. The amount of multiplayer activity (total user-minutes).
2. The number of users playing in a single session.
3. Compute, storage, and networking resources are required for a session.
4. Overhead for stand-by sessions.
An example:

IN P UT DEF IN IT IO N

12 minutes Average multiplayer gameplay minutes per user per month

100,000 users Unique users per month

4 users Average users per session


12 User Minutes 100,000 Users 1 Session Session Minutes
------------------ × ----------------- × ------------ = 300,000 -----------------
User⁄Month Month 4 Users Month

At 100,000 users, each averaging 12 user minutes per month, this comes out to 1.2 million user minutes.
Dividing this number by the average users per session (4) results in 300,000 total session minutes used.
In this example we are packing 3 servers on a 2-core D2_v3 virtual machine:

IN P UT DEF IN IT IO N

3 Servers Servers per virtual machine

D2_v3 Virtual machine size

300,000 Server Minutes 1 D2_v3 VM 100,000 D2_v3 VM Minutes


----------------------- x ------------ = ------------------------
Month 3 Servers Month

Since we are running 3 servers on our D2_v3 VM , we can divide the total session minutes used (300,000) by
the number of servers (3) to figure out approximately how many D2_v3 VM minutes (100,000) have been used
this month.
Traditional multiplayer server hosting may require you to pay for significant overhead capacity, to handle
natural variation in player activity.
It is common for games to have higher levels of concurrency during the weekends and holidays that require you
to "pre-pay" for more servers than necessary, as shown below.

PlayFab Multiplayer Server builds automatically scale with your player base. Servers are transitioned to the
active state by calling RequestMultiplayerServer, and are later recycled when your game server terminates
(typically the end of a "multiplayer round").
However, delivering this dynamic scaling with minimal allocation latency requires some overhead, which
originates from 2 key sources:
1. Standing-by ser vers - Players do not want to wait for servers, and PlayFab targets a 3 second response
time for fulfilling a server request. PlayFab will maintain a set of standing-by servers to ensure that
servers are immediately available. As this standing-by pool is consumed by new allocations, PlayFab
initializes new standing-by sessions. The amount of standing-by sessions required is dependent on how
fast new sessions are requested during peak utilization, and how quickly they can be created and
initialized.
2. Vir tual machine fragmentation - If you host multiple sessions on a single virtual machine, there can
sometimes be extra stand-by capacity due to fragmentation. In our example of 3 sessions per virtual
machine, a virtual machine might have only 1 active session, and the remaining two "spaces" are added
to the stand-by pool. Until the active session is terminated, the virtual machine must stay online - even if
the additional stand-by capacity is not needed.

NOTE
Typically, these sources of overhead increase the required compute-hours by 20%.

Calculating networking
Network egress can be a substantial expense, especially for large multiplayer sessions with many simultaneous
connected players (32+). During development and testing, run your server locally to get an estimate of its
network utilization during play.

IN P UT DEF IN IT IO N

1 Megabytes per second transmitted from the server during


active play

300,000 Session Minutes × 60 Seconds/Minute × 1 MBPS/Session = 18,000,000 MB

In this example, assume that testing shows that a multiplayer session sends 1 MB of data per second of active
play.
Since we earlier calculated 300,000 server minutes used in a month, we can estimate that 300,000 users x 60
MB per minute equals 18,000,000 MB of data sent per month.

How to pay
PlayFab offers three pathways for billing.
1. Billing through credit card.
2. Billing through PlayFab invoicing. This is ideal for many professional projects, but requires you to
contact our customer services group to get set up.
3. Billing through Azure & Microsoft Enterprise Agreements. This is ideal for organizations that may
have a volume deal with Azure or another Microsoft product line. Please contact our customer services
group or your Azure solutions specialist to learn more.
In all three options you will receive a detailed analysis of your multiplayer server activity in Game Manager.
However - for Azure/EA customers - the final invoicing through Azure is simplified, and will show these high
level line-items denominated in dollars:
PlayFab Essential Services
PlayFab Multiplayer Servers
Multiplayer servers - detailed price sheet
5/24/2022 • 56 minutes to read • Edit Online

PlayFab multiplayer servers operate on most generally available Azure virtual machine sizes and regions. These
are the most popular series for game developers providing progressively faster processors.

Recommended VMs
The Dav4 and Dasv4 series feature the AMD 2.35Ghz EPYCTM 7452 2nd Generation processor in a multi-
threaded configuration with up to 256 MB L3 cache, and each 8 cores have 8 MB of dedicated L3 cache. The
Dav4-series sizes offer a combination of vCPU, memory and temporary storage that is suitable for most
gaming workloads. The Dasv4 Azure VMs expose up to 96 vCPUs, 384 GBs of RAM, and 768 GBs of SSD-
based storage. Furthermore, the Azure Performance Improvement team has tuned Dasv4 VMs to be the most
stable, delivering the best price/performance ratio on Azure with no code changes needed.
The Eav4 and Easv4-series utilize AMD's 2.35Ghz EPYCTM7452 processor in a multi-threaded configuration
with up to 256MB L3 cache, increasing options for running most memory optimized workloads. The Eav4-
series and Easv4-series have the same memory and disk configurations as the Ev3 & Esv3-series, and are
ideal for memory-intensive applications.
The Dasv4 is now the recommended SKU for running game servers in Azure. For customers currently on the
Dv2, Fsv2 and Dv3 VMs, we highly recommend switching to Dasv4 as it offers the best ratio of price to CPU
performance and more memory than the Fsv2. Below is a comparison of the PlayFab Multiplayer Servers 2 core
SKUs. Prices are approximate as they vary based on the region selected.

VM Comparison Summary
A P P RO X. P RIC E
P ER A C U VS
SK U CPU RA M ( GB ) STO RA GE ( GB ) ACU D2V2

D2av4 AMD EPYCTM 8 50 230-260 -38%


7452

E2av4 AMD EPYCTM 16 50 230-260 -19%


7452

F2sv2 Intel Xeon® 4 16 195-210 -37%


Platinum 8168
(SkyLake)

D2v3 Intel Xeon® 8 50 160-190 -14%


E5-2673 v3
(Haswell)
processor
or<pr> E5-2673
v4 (Broadwell)
A P P RO X. P RIC E
P ER A C U VS
SK U CPU RA M ( GB ) STO RA GE ( GB ) ACU D2V2

D2v2 Intel Xeon® 8 100 210-150 0%


E5-2673 v3
(Haswell)
processor
or<pr> E5-2673
v4 (Broadwell)

A2v2 Various 4 20 100 +51%

Alternative VMs
The Fsv2-series is based on the Intel® Xeon® Platinum 8168 processor. It features a sustained all core
Turbo clock speed of 3.4 GHz and a maximum single-core turbo frequency of 3.7 GHz. Intel® AVX-512
instructions are new on Intel Scalable Processors. These instructions provide up to a 2X performance boost to
vector processing workloads on both single and double precision floating point operations. In other words,
they're really fast for any computational workload. At a lower per-hour list price, the Fsv2-series is the best
value in price-performance in the Azure portfolio based on the Azure Compute Unit (ACU) per vCPU.
The Dv2-series VMs features a powerful CPU and optimal CPU-to-memory configuration making them
suitable for most production workloads. The Dv2-series is about 35% faster than the D-series. Dv2-series
runs on the Intel® Xeon® 8171M 2.1GHz (Skylake), Intel® Xeon® E5-2673 v4 2.3 GHz (Broadwell), or
the Intel® Xeon® E5-2673 v3 2.4 GHz (Haswell) processors with the Intel Turbo Boost Technology 2.0.
The Av2-series VMs can be deployed on a variety of hardware types and processors. The size is throttled,
based upon the hardware, to offer consistent processor performance for the running instance, regardless of
the hardware it is deployed on.

NOTE
The following prices are per virtual machine compute hour.

VM Hourly Rates
REC O M M EN DED A LT ERN AT IVE

Dasv4, Dav4, Easv4, Eav4 Fsv2, Fv1, Dsv3, Dv3, Dsv2 ,Dv2, Av2

Av2
Av2 Standard is the latest generation of A-series virtual machines with similar CPU performance and faster disk.
These virtual machines are suitable for development workloads, build servers, code repositories, low-traffic
websites and web applications, micro services, early product experiments, and small databases. Like the prior A
Standard generation, Av2 virtual machines will include load balancing and auto-scaling at no additional charge.
back to top
US East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

A1v2 1 2 GiB 10 GiB $0.0473/hour $0.0715/hour


IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

A2v2 2 4 GiB 20 GiB $0.1001/hour $0.1496/hour

A4v2 4 8 GiB 40 GiB $0.2101/hour $0.3146/hour

A8v2 8 16 GiB 80 GiB $0.44/hour $0.66/hour

back to top
US East 2

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

A1v2 1 2 GiB 10 GiB $0.0473/hour $0.0715/hour

A2v2 2 4 GiB 20 GiB $0.1001/hour $0.1496/hour

A4v2 4 8 GiB 40 GiB $0.2101/hour $0.3146/hour

A8v2 8 16 GiB 80 GiB $0.44/hour $0.66/hour

back to top
US West

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

A1v2 1 2 GiB 10 GiB $0.0473/hour $0.0715/hour

A2v2 2 4 GiB 20 GiB $0.1001/hour $0.1496/hour

A4v2 4 8 GiB 40 GiB $0.2101/hour $0.3146/hour

A8v2 8 16 GiB 80 GiB $0.44/hour $0.66/hour

back to top
US West 2

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

A1v2 1 2 GiB 10 GiB $0.0396/hour $0.0594/hour

A2v2 2 4 GiB 20 GiB $0.0836/hour $0.1243/hour

A4v2 4 8 GiB 40 GiB $0.1749/hour $0.2618/hour

A8v2 8 16 GiB 80 GiB $0.3663/hour $0.55/hour

back to top
US Central
IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

A1v2 1 2 GiB 10 GiB $0.0473/hour $0.0715/hour

A2v2 2 4 GiB 20 GiB $0.1001/hour $0.1496/hour

A4v2 4 8 GiB 40 GiB $0.2101/hour $0.3146/hour

A8v2 8 16 GiB 80 GiB $0.44/hour $0.66/hour

back to top
US North Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

A1v2 1 2 GiB 10 GiB $0.0473/hour $0.0715/hour

A2v2 2 4 GiB 20 GiB $0.1001/hour $0.1496/hour

A4v2 4 8 GiB 40 GiB $0.2101/hour $0.3146/hour

A8v2 8 16 GiB 80 GiB $0.44/hour $0.66/hour

back to top
US South Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

A1v2 1 2 GiB 10 GiB $0.0473/hour $0.0715/hour

A2v2 2 4 GiB 20 GiB $0.1001/hour $0.1496/hour

A4v2 4 8 GiB 40 GiB $0.2101/hour $0.3146/hour

A8v2 8 16 GiB 80 GiB $0.44/hour $0.66/hour

back to top
US West Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

A1v2 1 2 GiB 10 GiB $0.044/hour $0.0649/hour

A2v2 2 4 GiB 20 GiB $0.0913/hour $0.1375/hour

A4v2 4 8 GiB 40 GiB $0.1925/hour $0.2882/hour

A8v2 8 16 GiB 80 GiB $0.4037/hour $0.605/hour

back to top
North Europe
IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

A1v2 1 2 GiB 10 GiB $0.0451/hour $0.0682/hour

A2v2 2 4 GiB 20 GiB $0.0957/hour $0.143/hour

A4v2 4 8 GiB 40 GiB $0.2013/hour $0.3014/hour

A8v2 8 16 GiB 80 GiB $0.4213/hour $0.6325/hour

back to top
West Europe

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

A1v2 1 2 GiB 10 GiB $0.0451/hour $0.0682/hour

A2v2 2 4 GiB 20 GiB $0.0957/hour $0.143/hour

A4v2 4 8 GiB 40 GiB $0.2013/hour $0.3014/hour

A8v2 8 16 GiB 80 GiB $0.4213/hour $0.6325/hour

back to top
France Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

A1v2 1 2 GiB 10 GiB $0.055/hour $0.0836/hour

A2v2 2 4 GiB 20 GiB $0.1166/hour $0.1749/hour

A4v2 4 8 GiB 40 GiB $0.2442/hour $0.3663/hour

A8v2 8 16 GiB 80 GiB $0.5137/hour $0.77/hour

back to top
India Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

A1v2 1 2 GiB 10 GiB $0.0517/hour $0.077/hour

A2v2 2 4 GiB 20 GiB $0.1078/hour $0.1617/hour

A4v2 4 8 GiB 40 GiB $0.2266/hour $0.341/hour

A8v2 8 16 GiB 80 GiB $0.4763/hour $0.715/hour

back to top
UAE North
IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

A1v2 1 2 GiB 10 GiB $0.0475/hour $0.0981/hour

A2v2 2 4 GiB 20 GiB $0.1003/hour $0.2013/hour

A4v2 4 8 GiB 40 GiB $0.2101/hour $0.4125/hour

A8v2 8 16 GiB 80 GiB $0.44/hour $0.8448/hour

back to top
Brazil South

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

A1v2 1 2 GiB 10 GiB $0.0671/hour $0.1012/hour

A2v2 2 4 GiB 20 GiB $0.1419/hour $0.2123/hour

A4v2 4 8 GiB 40 GiB $0.297/hour $0.4455/hour

A8v2 8 16 GiB 80 GiB $0.6237/hour $0.935/hour

back to top
South Africa North

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

A1v2 1 2 GiB 10 GiB $0.053/hour $0.1036/hour

A2v2 2 4 GiB 20 GiB $0.1122/hour $0.2134/hour

A4v2 4 8 GiB 40 GiB $0.2343/hour $0.4367/hour

A8v2 8 16 GiB 80 GiB $0.4906/hour $0.8954/hour

back to top
Australia East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

A1v2 1 2 GiB 10 GiB $0.055/hour $0.0836/hour

A2v2 2 4 GiB 20 GiB $0.1166/hour $0.1749/hour

A4v2 4 8 GiB 40 GiB $0.2442/hour $0.3663/hour

A8v2 8 16 GiB 80 GiB $0.5137/hour $0.77/hour

back to top
Australia South East
IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

A1v2 1 2 GiB 10 GiB $0.055/hour $0.0836/hour

A2v2 2 4 GiB 20 GiB $0.1166/hour $0.1749/hour

A4v2 4 8 GiB 40 GiB $0.2442/hour $0.3663/hour

A8v2 8 16 GiB 80 GiB $0.5137/hour $0.77/hour

back to top
Korea Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

A1v2 1 2 GiB 10 GiB $0.0539/hour $0.0891/hour

A2v2 2 4 GiB 20 GiB $0.1122/hour $0.187/hour

A4v2 4 8 GiB 40 GiB $0.2354/hour $0.3916/hour

A8v2 8 16 GiB 80 GiB $0.495/hour $0.8228/hour

back to top
Japan East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

A1v2 1 2 GiB 10 GiB $0.0594/hour $0.0891/hour

A2v2 2 4 GiB 20 GiB $0.1243/hour $0.187/hour

A4v2 4 8 GiB 40 GiB $0.2618/hour $0.3927/hour

A8v2 8 16 GiB 80 GiB $0.55/hour $0.825/hour

back to top
Japan West

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

A1v2 1 2 GiB 10 GiB $0.0594/hour $0.0891/hour

A2v2 2 4 GiB 20 GiB $0.1243/hour $0.187/hour

A4v2 4 8 GiB 40 GiB $0.2618/hour $0.3927/hour

A8v2 8 16 GiB 80 GiB $0.55/hour $0.825/hour

back to top
East Asia
IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

A1v2 1 2 GiB 10 GiB $0.055/hour $0.0836/hour

A2v2 2 4 GiB 20 GiB $0.1166/hour $0.1749/hour

A4v2 4 8 GiB 40 GiB $0.2442/hour $0.3663/hour

A8v2 8 16 GiB 80 GiB $0.5137/hour $0.77/hour

back to top
South East Asia

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

A1v2 1 2 GiB 10 GiB $0.0495/hour $0.0748/hour

A2v2 2 4 GiB 20 GiB $0.1045/hour $0.1562/hour

A4v2 4 8 GiB 40 GiB $0.2178/hour $0.3278/hour

A8v2 8 16 GiB 80 GiB $0.4587/hour $0.6875/hour

Dv2
The Dv2-series virtual machines run on the Intel® Xeon® Platinum 8272CL processor (second generation
Intel® Xeon® Scalable processors), Intel® Xeon® 8171M 2.1GHz (Skylake), Intel® Xeon® E5-2673 v4
2.3 GHz (Broadwell), or the Intel® Xeon® E5-2673 v3 2.4 GHz (Haswell) processors with the Intel Turbo Boost
Technology 2.0. The D1-5 v2 sizes offer a balanced combination of vCPU(s), memory, and local disk for most
production workloads.
back to top
US East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1v2 1 3.5 GiB 50 GiB $0.0803/hour $0.1386/hour

D2v2 2 7 GiB 100 GiB $0.1606/hour $0.2772/hour

D4v2 4 14 GiB 200 GiB $0.3223/hour $0.5544/hour

D8v2 8 28 GiB 400 GiB $0.6435/hour $1.1088/hour

D16v2 16 56 GiB 800 GiB $1.287/hour $2.2176/hour

back to top
US East 2

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1v2 1 3.5 GiB 50 GiB $0.0627/hour $0.1287/hour


IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2v2 2 7 GiB 100 GiB $0.1254/hour $0.2574/hour

D4v2 4 14 GiB 200 GiB $0.2519/hour $0.5148/hour

D8v2 8 28 GiB 400 GiB $0.5038/hour $1.0296/hour

D16v2 16 56 GiB 800 GiB $1.0076/hour $2.0592/hour

back to top
US West

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1v2 1 3.5 GiB 50 GiB $0.077/hour $0.1386/hour

D2v2 2 7 GiB 100 GiB $0.154/hour $0.2772/hour

D4v2 4 14 GiB 200 GiB $0.3069/hour $0.5544/hour

D8v2 8 28 GiB 400 GiB $0.6149/hour $1.1088/hour

D16v2 16 56 GiB 800 GiB $1.2287/hour $2.2176/hour

back to top
US West 2

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1v2 1 3.5 GiB 50 GiB $0.0627/hour $0.1287/hour

D2v2 2 7 GiB 100 GiB $0.1254/hour $0.2574/hour

D4v2 4 14 GiB 200 GiB $0.2519/hour $0.5148/hour

D8v2 8 28 GiB 400 GiB $0.5038/hour $1.0296/hour

D16v2 16 56 GiB 800 GiB $1.0076/hour $2.0592/hour

back to top
US Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1v2 1 3.5 GiB 50 GiB $0.0803/hour $0.1386/hour

D2v2 2 7 GiB 100 GiB $0.1606/hour $0.2772/hour

D4v2 4 14 GiB 200 GiB $0.3223/hour $0.5544/hour

D8v2 8 28 GiB 400 GiB $0.6435/hour $1.1088/hour


IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D16v2 16 56 GiB 800 GiB $1.287/hour $2.2176/hour

back to top
US North Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1v2 1 3.5 GiB 50 GiB $0.0803/hour $0.1386/hour

D2v2 2 7 GiB 100 GiB $0.1606/hour $0.2772/hour

D4v2 4 14 GiB 200 GiB $0.3223/hour $0.5544/hour

D8v2 8 28 GiB 400 GiB $0.6435/hour $1.1088/hour

D16v2 16 56 GiB 800 GiB $1.287/hour $2.2176/hour

back to top
US South Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1v2 1 3.5 GiB 50 GiB $0.07/hour $0.1287/hour

D2v2 2 7 GiB 100 GiB $0.1397/hour $0.2574/hour

D4v2 4 14 GiB 200 GiB $0.2794/hour $0.5148/hour

D8v2 8 28 GiB 400 GiB $0.5599/hour $1.0296/hour

D16v2 16 56 GiB 800 GiB $1.1187/hour $2.0592/hour

back to top
US West Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1v2 1 3.5 GiB 50 GiB $0.07/hour $0.1287/hour

D2v2 2 7 GiB 100 GiB $0.1397/hour $0.2574/hour

D4v2 4 14 GiB 200 GiB $0.2794/hour $0.5148/hour

D8v2 8 28 GiB 400 GiB $0.5599/hour $1.0296/hour

D16v2 16 56 GiB 800 GiB $1.1187/hour $2.0592/hour

back to top
North Europe
IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1v2 1 3.5 GiB 50 GiB $0.0724/hour $0.1276/hour

D2v2 2 7 GiB 100 GiB $0.1452/hour $0.2552/hour

D4v2 4 14 GiB 200 GiB $0.2893/hour $0.5115/hour

D8v2 8 28 GiB 400 GiB $0.5797/hour $1.0219/hour

D16v2 16 56 GiB 800 GiB $1.1583/hour $2.0438/hour

back to top
West Europe

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1v2 1 3.5 GiB 50 GiB $0.0747/hour $0.1463/hour

D2v2 2 7 GiB 100 GiB $0.1496/hour $0.2926/hour

D4v2 4 14 GiB 200 GiB $0.2992/hour $0.5863/hour

D8v2 8 28 GiB 400 GiB $0.5984/hour $1.1726/hour

D16v2 16 56 GiB 800 GiB $1.1957/hour $2.3441/hour

back to top
France Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1v2 1 3.5 GiB 50 GiB $0.0965/hour $0.1617/hour

D2v2 2 7 GiB 100 GiB $0.1925/hour $0.3234/hour

D4v2 4 14 GiB 200 GiB $0.3861/hour $0.6468/hour

D8v2 8 28 GiB 400 GiB $0.7722/hour $1.2936/hour

D16v2 16 56 GiB 800 GiB $1.5444/hour $2.5861/hour

back to top
India Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1v2 1 3.5 GiB 50 GiB $0.0924/hour $0.143/hour

D2v2 2 7 GiB 100 GiB $0.1859/hour $0.2871/hour

D4v2 4 14 GiB 200 GiB $0.3707/hour $0.5731/hour


IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D8v2 8 28 GiB 400 GiB $0.7425/hour $1.1473/hour

D16v2 16 56 GiB 800 GiB $1.485/hour $2.2946/hour

back to top
UAE North

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1v2 1 3.5 GiB 50 GiB $0.0756/hour $0.1265/hour

D2v2 2 7 GiB 100 GiB $0.1507/hour $0.2519/hour

D4v2 4 14 GiB 200 GiB $0.3025/hour $0.5049/hour

D8v2 8 28 GiB 400 GiB $0.605/hour $1.0098/hour

D16v2 16 56 GiB 800 GiB $1.2089/hour $2.0185/hour

back to top
Brazil South

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1v2 1 3.5 GiB 50 GiB $0.0942/hour $0.1452/hour

D2v2 2 7 GiB 100 GiB $0.1881/hour $0.2893/hour

D4v2 4 14 GiB 200 GiB $0.3773/hour $0.5797/hour

D8v2 8 28 GiB 400 GiB $0.7535/hour $1.1583/hour

D16v2 16 56 GiB 800 GiB $1.507/hour $2.3166/hour

back to top
South Africa North

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1v2 1 3.5 GiB 50 GiB $0.0844/hour $0.1353/hour

D2v2 2 7 GiB 100 GiB $0.1683/hour $0.2695/hour

D4v2 4 14 GiB 200 GiB $0.3377/hour $0.5401/hour

D8v2 8 28 GiB 400 GiB $0.6754/hour $1.0802/hour

D16v2 16 56 GiB 800 GiB $1.3497/hour $2.1593/hour

back to top
Australia East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1v2 1 3.5 GiB 50 GiB $0.0924/hour $0.154/hour

D2v2 2 7 GiB 100 GiB $0.1848/hour $0.3091/hour

D4v2 4 14 GiB 200 GiB $0.3696/hour $0.6182/hour

D8v2 8 28 GiB 400 GiB $0.7403/hour $1.2353/hour

D16v2 16 56 GiB 800 GiB $1.4795/hour $2.4695/hour

back to top
Australia South East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1v2 1 3.5 GiB 50 GiB $0.0856/hour $0.154/hour

D2v2 2 7 GiB 100 GiB $0.1714/hour $0.3091/hour

D4v2 4 14 GiB 200 GiB $0.3421/hour $0.6182/hour

D8v2 8 28 GiB 400 GiB $0.6853/hour $1.2353/hour

D16v2 16 56 GiB 800 GiB $1.3706/hour $2.4695/hour

back to top
Korea Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1v2 1 3.5 GiB 50 GiB $0.0907/hour $0.1419/hour

D2v2 2 7 GiB 100 GiB $0.1815/hour $0.2827/hour

D4v2 4 14 GiB 200 GiB $0.363/hour $0.5654/hour

D8v2 8 28 GiB 400 GiB $0.726/hour $1.1308/hour

D16v2 16 56 GiB 800 GiB $1.4531/hour $2.2627/hour

back to top
Japan East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1v2 1 3.5 GiB 50 GiB $0.1122/hour $0.1496/hour

D2v2 2 7 GiB 100 GiB $0.2255/hour $0.3003/hour


IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D4v2 4 14 GiB 200 GiB $0.4499/hour $0.6006/hour

D8v2 8 28 GiB 400 GiB $0.8998/hour $1.2001/hour

D16v2 16 56 GiB 800 GiB $1.7996/hour $2.4013/hour

back to top
Japan West

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1v2 1 3.5 GiB 50 GiB $0.1001/hour $0.1441/hour

D2v2 2 7 GiB 100 GiB $0.2002/hour $0.2893/hour

D4v2 4 14 GiB 200 GiB $0.4015/hour $0.5786/hour

D8v2 8 28 GiB 400 GiB $0.8019/hour $1.1561/hour

D16v2 16 56 GiB 800 GiB $1.6049/hour $2.3122/hour

back to top
East Asia

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1v2 1 3.5 GiB 50 GiB $0.1177/hour $0.1837/hour

D2v2 2 7 GiB 100 GiB $0.2354/hour $0.3663/hour

D4v2 4 14 GiB 200 GiB $0.4708/hour $0.7337/hour

D8v2 8 28 GiB 400 GiB $0.9427/hour $1.4663/hour

D16v2 16 56 GiB 800 GiB $1.8854/hour $2.9326/hour

back to top
South East Asia

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1v2 1 3.5 GiB 50 GiB $0.0868/hour $0.1595/hour

D2v2 2 7 GiB 100 GiB $0.1738/hour $0.319/hour

D4v2 4 14 GiB 200 GiB $0.3476/hour $0.638/hour

D8v2 8 28 GiB 400 GiB $0.6941/hour $1.2749/hour

D16v2 16 56 GiB 800 GiB $1.3893/hour $2.5498/hour


Dsv2
The Dsv2-series virtual machines run on the Intel® Xeon® Platinum 8272CL processor (second generation
Intel® Xeon® Scalable processors), Intel® Xeon® 8171M 2.1GHz (Skylake), Intel® Xeon® E5-2673 v4
2.3 GHz (Broadwell), or the Intel® Xeon® E5-2673 v3 2.4 GHz (Haswell) processors with the Intel Turbo Boost
Technology 2.0 and support Premium SSDs disk storage. The Dsv2-series sizes offer a balanced combination of
vCPU(s), memory, and local disk for most production workloads.
back to top
US East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1sv2 1 3.5 GiB 7 GiB $0.0763/hour $0.1317/hour

D2sv2 2 7 GiB 14 GiB $0.1526/hour $0.2633/hour

D4sv2 4 14 GiB 28 GiB $0.3062/hour $0.5267/hour

D8sv2 8 28 GiB 56 GiB $0.6113/hour $1.0534/hour

D16sv2 16 56 GiB 112 GiB $1.2227/hour $2.1067/hour

back to top
US East 2

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1sv2 1 3.5 GiB 7 GiB $0.0596/hour $0.1223/hour

D2sv2 2 7 GiB 14 GiB $0.1191/hour $0.2445/hour

D4sv2 4 14 GiB 28 GiB $0.2393/hour $0.4891/hour

D8sv2 8 28 GiB 56 GiB $0.4786/hour $0.9781/hour

D16sv2 16 56 GiB 112 GiB $0.9572/hour $1.9562/hour

back to top
US West

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1sv2 1 3.5 GiB 7 GiB $0.0732/hour $0.1317/hour

D2sv2 2 7 GiB 14 GiB $0.1463/hour $0.2633/hour

D4sv2 4 14 GiB 28 GiB $0.2916/hour $0.5267/hour

D8sv2 8 28 GiB 56 GiB $0.5842/hour $1.0534/hour

D16sv2 16 56 GiB 112 GiB $1.1673/hour $2.1067/hour

back to top
US West 2

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1sv2 1 3.5 GiB 7 GiB $0.0596/hour $0.1223/hour

D2sv2 2 7 GiB 14 GiB $0.1191/hour $0.2445/hour

D4sv2 4 14 GiB 28 GiB $0.2393/hour $0.4891/hour

D8sv2 8 28 GiB 56 GiB $0.4786/hour $0.9781/hour

D16sv2 16 56 GiB 112 GiB $0.9572/hour $1.9562/hour

back to top
US Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1sv2 1 3.5 GiB 7 GiB $0.0763/hour $0.1317/hour

D2sv2 2 7 GiB 14 GiB $0.1526/hour $0.2633/hour

D4sv2 4 14 GiB 28 GiB $0.3062/hour $0.5267/hour

D8sv2 8 28 GiB 56 GiB $0.6113/hour $1.0534/hour

D16sv2 16 56 GiB 112 GiB $1.2227/hour $2.1067/hour

back to top
US North Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1sv2 1 3.5 GiB 7 GiB $0.0763/hour $0.1317/hour

D2sv2 2 7 GiB 14 GiB $0.1526/hour $0.2633/hour

D4sv2 4 14 GiB 28 GiB $0.3062/hour $0.5267/hour

D8sv2 8 28 GiB 56 GiB $0.6113/hour $1.0534/hour

D16sv2 16 56 GiB 112 GiB $1.2227/hour $2.1067/hour

back to top
US South Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1sv2 1 3.5 GiB 7 GiB $0.0665/hour $0.1223/hour

D2sv2 2 7 GiB 14 GiB $0.1327/hour $0.2445/hour


IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D4sv2 4 14 GiB 28 GiB $0.2654/hour $0.4891/hour

D8sv2 8 28 GiB 56 GiB $0.5319/hour $0.9781/hour

D16sv2 16 56 GiB 112 GiB $1.0628/hour $1.9562/hour

back to top
US West Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1sv2 1 3.5 GiB 7 GiB $0.0665/hour $0.1223/hour

D2sv2 2 7 GiB 14 GiB $0.1327/hour $0.2445/hour

D4sv2 4 14 GiB 28 GiB $0.2654/hour $0.4891/hour

D8sv2 8 28 GiB 56 GiB $0.5319/hour $0.9781/hour

D16sv2 16 56 GiB 112 GiB $1.0628/hour $1.9562/hour

back to top
North Europe

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1sv2 1 3.5 GiB 7 GiB $0.0688/hour $0.1212/hour

D2sv2 2 7 GiB 14 GiB $0.1379/hour $0.2424/hour

D4sv2 4 14 GiB 28 GiB $0.2748/hour $0.4859/hour

D8sv2 8 28 GiB 56 GiB $0.5507/hour $0.9708/hour

D16sv2 16 56 GiB 112 GiB $1.1004/hour $1.9416/hour

back to top
West Europe

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1sv2 1 3.5 GiB 7 GiB $0.071/hour $0.139/hour

D2sv2 2 7 GiB 14 GiB $0.1421/hour $0.278/hour

D4sv2 4 14 GiB 28 GiB $0.2842/hour $0.557/hour

D8sv2 8 28 GiB 56 GiB $0.5685/hour $1.114/hour

D16sv2 16 56 GiB 112 GiB $1.1359/hour $2.2269/hour


back to top
France Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1sv2 1 3.5 GiB 7 GiB $0.0916/hour $0.1536/hour

D2sv2 2 7 GiB 14 GiB $0.1829/hour $0.3072/hour

D4sv2 4 14 GiB 28 GiB $0.3668/hour $0.6145/hour

D8sv2 8 28 GiB 56 GiB $0.7336/hour $1.2289/hour

D16sv2 16 56 GiB 112 GiB $1.4672/hour $2.4568/hour

back to top
India Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1sv2 1 3.5 GiB 7 GiB $0.0878/hour $0.1359/hour

D2sv2 2 7 GiB 14 GiB $0.1766/hour $0.2727/hour

D4sv2 4 14 GiB 28 GiB $0.3522/hour $0.5444/hour

D8sv2 8 28 GiB 56 GiB $0.7054/hour $1.0899/hour

D16sv2 16 56 GiB 112 GiB $1.4108/hour $2.1799/hour

back to top
UAE North

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1sv2 1 3.5 GiB 7 GiB $0.0718/hour $0.1202/hour

D2sv2 2 7 GiB 14 GiB $0.1432/hour $0.2393/hour

D4sv2 4 14 GiB 28 GiB $0.2874/hour $0.4797/hour

D8sv2 8 28 GiB 56 GiB $0.5748/hour $0.9593/hour

D16sv2 16 56 GiB 112 GiB $1.1485/hour $1.9176/hour

back to top
Brazil South

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1sv2 1 3.5 GiB 7 GiB $0.0895/hour $0.1379/hour


IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2sv2 2 7 GiB 14 GiB $0.1787/hour $0.2748/hour

D4sv2 4 14 GiB 28 GiB $0.3584/hour $0.5507/hour

D8sv2 8 28 GiB 56 GiB $0.7158/hour $1.1004/hour

D16sv2 16 56 GiB 112 GiB $1.4317/hour $2.2008/hour

back to top
South Africa North

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1sv2 1 3.5 GiB 7 GiB $0.0802/hour $0.1285/hour

D2sv2 2 7 GiB 14 GiB $0.1599/hour $0.256/hour

D4sv2 4 14 GiB 28 GiB $0.3208/hour $0.5131/hour

D8sv2 8 28 GiB 56 GiB $0.6416/hour $1.0262/hour

D16sv2 16 56 GiB 112 GiB $1.2822/hour $2.0513/hour

back to top
Australia East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1sv2 1 3.5 GiB 7 GiB $0.0878/hour $0.1463/hour

D2sv2 2 7 GiB 14 GiB $0.1756/hour $0.2936/hour

D4sv2 4 14 GiB 28 GiB $0.3511/hour $0.5873/hour

D8sv2 8 28 GiB 56 GiB $0.7033/hour $1.1735/hour

D16sv2 16 56 GiB 112 GiB $1.4055/hour $2.346/hour

back to top
Australia South East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1sv2 1 3.5 GiB 7 GiB $0.0813/hour $0.1463/hour

D2sv2 2 7 GiB 14 GiB $0.1628/hour $0.2936/hour

D4sv2 4 14 GiB 28 GiB $0.325/hour $0.5873/hour

D8sv2 8 28 GiB 56 GiB $0.651/hour $1.1735/hour


IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D16sv2 16 56 GiB 112 GiB $1.3021/hour $2.346/hour

back to top
Korea Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1sv2 1 3.5 GiB 7 GiB $0.0862/hour $0.1348/hour

D2sv2 2 7 GiB 14 GiB $0.1724/hour $0.2686/hour

D4sv2 4 14 GiB 28 GiB $0.3448/hour $0.5371/hour

D8sv2 8 28 GiB 56 GiB $0.6897/hour $1.0743/hour

D16sv2 16 56 GiB 112 GiB $1.3804/hour $2.1496/hour

back to top
Japan East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1sv2 1 3.5 GiB 7 GiB $0.1066/hour $0.1421/hour

D2sv2 2 7 GiB 14 GiB $0.2142/hour $0.2853/hour

D4sv2 4 14 GiB 28 GiB $0.4274/hour $0.5706/hour

D8sv2 8 28 GiB 56 GiB $0.8548/hour $1.1401/hour

D16sv2 16 56 GiB 112 GiB $1.7096/hour $2.2812/hour

back to top
Japan West

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1sv2 1 3.5 GiB 7 GiB $0/hour $0.1369/hour

D2sv2 2 7 GiB 14 GiB $0/hour $0.2748/hour

D4sv2 4 14 GiB 28 GiB $0/hour $0.5497/hour

D8sv2 8 28 GiB 56 GiB $0/hour $1.0983/hour

D16sv2 16 56 GiB 112 GiB $0/hour $2.1966/hour

back to top
East Asia
IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1sv2 1 3.5 GiB 7 GiB $0.1118/hour $0.1745/hour

D2sv2 2 7 GiB 14 GiB $0.2236/hour $0.348/hour

D4sv2 4 14 GiB 28 GiB $0.4473/hour $0.697/hour

D8sv2 8 28 GiB 56 GiB $0.8956/hour $1.393/hour

D16sv2 16 56 GiB 112 GiB $1.7911/hour $2.786/hour

back to top
South East Asia

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D1sv2 1 3.5 GiB 7 GiB $0.0825/hour $0.1515/hour

D2sv2 2 7 GiB 14 GiB $0.1651/hour $0.303/hour

D4sv2 4 14 GiB 28 GiB $0.3302/hour $0.6061/hour

D8sv2 8 28 GiB 56 GiB $0.6594/hour $1.2112/hour

D16sv2 16 56 GiB 112 GiB $1.3198/hour $2.4223/hour

Dv3
The Dv3-series virtual machines run on the Intel® Xeon® Platinum 8272CL processor (second generation
Intel® Xeon® Scalable processors), Intel® Xeon® 8171M 2.1GHz (Skylake), Intel® Xeon® E5-2673 v4
2.3 GHz (Broadwell), or the Intel® Xeon® E5-2673 v3 2.4 GHz (Haswell) processors in a hyper-threaded
configuration. The Dv3-series sizes offer a combination of vCPU(s), memory, and local disk well suited for most
production workloads.
back to top
US East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2v3 2 8 GiB 50 GiB $0.1056/hour $0.2068/hour

D4v3 4 16 GiB 100 GiB $0.2112/hour $0.4136/hour

D8v3 8 32 GiB 200 GiB $0.4224/hour $0.8272/hour

D16v3 16 64 GiB 400 GiB $0.8448/hour $1.6544/hour

back to top
US East 2
IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2v3 2 8 GiB 50 GiB $0.1056/hour $0.2068/hour

D4v3 4 16 GiB 100 GiB $0.2112/hour $0.4136/hour

D8v3 8 32 GiB 200 GiB $0.4224/hour $0.8272/hour

D16v3 16 64 GiB 400 GiB $0.8448/hour $1.6544/hour

back to top
US West

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2v3 2 8 GiB 50 GiB $0.1287/hour $0.2299/hour

D4v3 4 16 GiB 100 GiB $0.2574/hour $0.4598/hour

D8v3 8 32 GiB 200 GiB $0.5148/hour $0.9196/hour

D16v3 16 64 GiB 400 GiB $1.0296/hour $1.8392/hour

back to top
US West 2

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2v3 2 8 GiB 50 GiB $0.1056/hour $0.2068/hour

D4v3 4 16 GiB 100 GiB $0.2112/hour $0.4136/hour

D8v3 8 32 GiB 200 GiB $0.4224/hour $0.8272/hour

D16v3 16 64 GiB 400 GiB $0.8448/hour $1.6544/hour

back to top
US Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2v3 2 8 GiB 50 GiB $0.121/hour $0.2321/hour

D4v3 4 16 GiB 100 GiB $0.242/hour $0.4642/hour

D8v3 8 32 GiB 200 GiB $0.484/hour $0.9295/hour

D16v3 16 64 GiB 400 GiB $0.968/hour $1.859/hour

back to top
US North Central
IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2v3 2 8 GiB 50 GiB $0.11/hour $0.2112/hour

D4v3 4 16 GiB 100 GiB $0.22/hour $0.4224/hour

D8v3 8 32 GiB 200 GiB $0.44/hour $0.8448/hour

D16v3 16 64 GiB 400 GiB $0.88/hour $1.6896/hour

back to top
US South Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2v3 2 8 GiB 50 GiB $0.121/hour $0.2321/hour

D4v3 4 16 GiB 100 GiB $0.242/hour $0.4642/hour

D8v3 8 32 GiB 200 GiB $0.484/hour $0.9295/hour

D16v3 16 64 GiB 400 GiB $0.968/hour $1.859/hour

back to top
US West Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2v3 2 8 GiB 50 GiB $0.121/hour $0.2321/hour

D4v3 4 16 GiB 100 GiB $0.242/hour $0.4642/hour

D8v3 8 32 GiB 200 GiB $0.484/hour $0.9295/hour

D16v3 16 64 GiB 400 GiB $0.968/hour $1.859/hour

back to top
North Europe

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2v3 2 8 GiB 50 GiB $0.1177/hour $0.2189/hour

D4v3 4 16 GiB 100 GiB $0.2354/hour $0.4378/hour

D8v3 8 32 GiB 200 GiB $0.4708/hour $0.8756/hour

D16v3 16 64 GiB 400 GiB $0.9416/hour $1.7512/hour

back to top
West Europe
IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2v3 2 8 GiB 50 GiB $0.132/hour $0.2332/hour

D4v3 4 16 GiB 100 GiB $0.264/hour $0.4664/hour

D8v3 8 32 GiB 200 GiB $0.528/hour $0.9328/hour

D16v3 16 64 GiB 400 GiB $1.056/hour $1.8656/hour

back to top
France Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2v3 2 8 GiB 50 GiB $0.1232/hour $0.2244/hour

D4v3 4 16 GiB 100 GiB $0.2464/hour $0.4488/hour

D8v3 8 32 GiB 200 GiB $0.4928/hour $0.8976/hour

D16v3 16 64 GiB 400 GiB $0.9856/hour $1.7952/hour

back to top
India Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2v3 2 8 GiB 50 GiB $0.1155/hour $0.2167/hour

D4v3 4 16 GiB 100 GiB $0.231/hour $0.4334/hour

D8v3 8 32 GiB 200 GiB $0.462/hour $0.8668/hour

D16v3 16 64 GiB 400 GiB $0.924/hour $1.7336/hour

back to top
UAE North

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2v3 2 8 GiB 50 GiB $0.132/hour $0.2332/hour

D4v3 4 16 GiB 100 GiB $0.264/hour $0.4664/hour

D8v3 8 32 GiB 200 GiB $0.528/hour $0.9328/hour

D16v3 16 64 GiB 400 GiB $1.056/hour $1.8656/hour

back to top
Brazil South
IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2v3 2 8 GiB 50 GiB $0.1749/hour $0.2761/hour

D4v3 4 16 GiB 100 GiB $0.3498/hour $0.5522/hour

D8v3 8 32 GiB 200 GiB $0.6996/hour $1.1044/hour

D16v3 16 64 GiB 400 GiB $1.3992/hour $2.2088/hour

back to top
South Africa North

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2v3 2 8 GiB 50 GiB $0.1397/hour $0.2409/hour

D4v3 4 16 GiB 100 GiB $0.2794/hour $0.4818/hour

D8v3 8 32 GiB 200 GiB $0.5588/hour $0.9636/hour

D16v3 16 64 GiB 400 GiB $1.1176/hour $1.9272/hour

back to top
Australia East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2v3 2 8 GiB 50 GiB $0.1375/hour $0.2387/hour

D4v3 4 16 GiB 100 GiB $0.275/hour $0.4774/hour

D8v3 8 32 GiB 200 GiB $0.55/hour $0.9548/hour

D16v3 16 64 GiB 400 GiB $1.1/hour $1.9096/hour

back to top
Australia South East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2v3 2 8 GiB 50 GiB $0.1375/hour $0.2387/hour

D4v3 4 16 GiB 100 GiB $0.275/hour $0.4774/hour

D8v3 8 32 GiB 200 GiB $0.55/hour $0.9548/hour

D16v3 16 64 GiB 400 GiB $1.1/hour $1.9096/hour

back to top
Korea Central
IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2v3 2 8 GiB 50 GiB $0.1353/hour $0.2365/hour

D4v3 4 16 GiB 100 GiB $0.2706/hour $0.473/hour

D8v3 8 32 GiB 200 GiB $0.5412/hour $0.946/hour

D16v3 16 64 GiB 400 GiB $1.0824/hour $1.892/hour

back to top
Japan East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2v3 2 8 GiB 50 GiB $0.1419/hour $0.2431/hour

D4v3 4 16 GiB 100 GiB $0.2838/hour $0.4862/hour

D8v3 8 32 GiB 200 GiB $0.5676/hour $0.9724/hour

D16v3 16 64 GiB 400 GiB $1.1352/hour $1.9448/hour

back to top
Japan West

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2v3 2 8 GiB 50 GiB $0.2002/hour $0.2431/hour

D4v3 4 16 GiB 100 GiB $0.4015/hour $0.4862/hour

D8v3 8 32 GiB 200 GiB $0.8019/hour $0.9724/hour

D16v3 16 64 GiB 400 GiB $1.6049/hour $1.9448/hour

back to top
East Asia

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2v3 2 8 GiB 50 GiB $0.1452/hour $0.2464/hour

D4v3 4 16 GiB 100 GiB $0.2904/hour $0.4928/hour

D8v3 8 32 GiB 200 GiB $0.5808/hour $0.9856/hour

D16v3 16 64 GiB 400 GiB $1.1616/hour $1.9712/hour

back to top
South East Asia
IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2v3 2 8 GiB 50 GiB $0.1375/hour $0.2387/hour

D4v3 4 16 GiB 100 GiB $0.275/hour $0.4774/hour

D8v3 8 32 GiB 200 GiB $0.55/hour $0.9548/hour

D16v3 16 64 GiB 400 GiB $1.1/hour $1.9096/hour

Dsv3
The Dsv3-series support premium storage and run on the Intel® Xeon® Platinum 8272CL processor (second
generation Intel® Xeon® Scalable processors), Intel® Xeon® 8171M 2.1GHz (Skylake), Intel® Xeon®
E5-2673 v4 2.3 GHz (Broadwell), or the Intel® Xeon® E5-2673 v3 2.4 GHz (Haswell) processors with Intel
Turbo Boost Technology 2.0 and feature Intel® Hyper-Threading Technology. The Dsv3-series sizes offer a
combination of vCPU(s), memory, and temporary storage well suited for most production workloads.
back to top
US East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2sv3 2 8 GiB 16 GiB $0.1003/hour $0.1965/hour

D4sv3 4 16 GiB 32 GiB $0.2006/hour $0.3929/hour

D8sv3 8 32 GiB 64 GiB $0.4013/hour $0.7858/hour

D16sv3 16 64 GiB 128 GiB $0.8026/hour $1.5717/hour

back to top
US East 2

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2sv3 2 8 GiB 16 GiB $0.1003/hour $0.1965/hour

D4sv3 4 16 GiB 32 GiB $0.2006/hour $0.3929/hour

D8sv3 8 32 GiB 64 GiB $0.4013/hour $0.7858/hour

D16sv3 16 64 GiB 128 GiB $0.8026/hour $1.5717/hour

back to top
US West

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2sv3 2 8 GiB 16 GiB $0.1223/hour $0.2184/hour

D4sv3 4 16 GiB 32 GiB $0.2445/hour $0.4368/hour


IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D8sv3 8 32 GiB 64 GiB $0.4891/hour $0.8736/hour

D16sv3 16 64 GiB 128 GiB $0.9781/hour $1.7472/hour

back to top
US West 2

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2sv3 2 8 GiB 16 GiB $0.1003/hour $0.1965/hour

D4sv3 4 16 GiB 32 GiB $0.2006/hour $0.3929/hour

D8sv3 8 32 GiB 64 GiB $0.4013/hour $0.7858/hour

D16sv3 16 64 GiB 128 GiB $0.8026/hour $1.5717/hour

back to top
US Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2sv3 2 8 GiB 16 GiB $0.1149/hour $0.2205/hour

D4sv3 4 16 GiB 32 GiB $0.2299/hour $0.441/hour

D8sv3 8 32 GiB 64 GiB $0.4598/hour $0.883/hour

D16sv3 16 64 GiB 128 GiB $0.9196/hour $1.766/hour

back to top
US North Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2sv3 2 8 GiB 16 GiB $0.1045/hour $0.2006/hour

D4sv3 4 16 GiB 32 GiB $0.209/hour $0.4013/hour

D8sv3 8 32 GiB 64 GiB $0.418/hour $0.8026/hour

D16sv3 16 64 GiB 128 GiB $0.836/hour $1.6051/hour

back to top
US South Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2sv3 2 8 GiB 16 GiB $0.1149/hour $0.2205/hour


IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D4sv3 4 16 GiB 32 GiB $0.2299/hour $0.441/hour

D8sv3 8 32 GiB 64 GiB $0.4598/hour $0.883/hour

D16sv3 16 64 GiB 128 GiB $0.9196/hour $1.766/hour

back to top
US West Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2sv3 2 8 GiB 16 GiB $0.1149/hour $0.2205/hour

D4sv3 4 16 GiB 32 GiB $0.2299/hour $0.441/hour

D8sv3 8 32 GiB 64 GiB $0.4598/hour $0.883/hour

D16sv3 16 64 GiB 128 GiB $0.9196/hour $1.766/hour

back to top
North Europe

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2sv3 2 8 GiB 16 GiB $0.1118/hour $0.208/hour

D4sv3 4 16 GiB 32 GiB $0.2236/hour $0.4159/hour

D8sv3 8 32 GiB 64 GiB $0.4473/hour $0.8318/hour

D16sv3 16 64 GiB 128 GiB $0.8945/hour $1.6636/hour

back to top
West Europe

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2sv3 2 8 GiB 16 GiB $0.1254/hour $0.2215/hour

D4sv3 4 16 GiB 32 GiB $0.2508/hour $0.4431/hour

D8sv3 8 32 GiB 64 GiB $0.5016/hour $0.8862/hour

D16sv3 16 64 GiB 128 GiB $1.0032/hour $1.7723/hour

back to top
France Central
IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2sv3 2 8 GiB 16 GiB $0.117/hour $0.2132/hour

D4sv3 4 16 GiB 32 GiB $0.2341/hour $0.4264/hour

D8sv3 8 32 GiB 64 GiB $0.4682/hour $0.8527/hour

D16sv3 16 64 GiB 128 GiB $0.9363/hour $1.7054/hour

back to top
India Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2sv3 2 8 GiB 16 GiB $0.1097/hour $0.2059/hour

D4sv3 4 16 GiB 32 GiB $0.2194/hour $0.4117/hour

D8sv3 8 32 GiB 64 GiB $0.4389/hour $0.8235/hour

D16sv3 16 64 GiB 128 GiB $0.8778/hour $1.6469/hour

back to top
UAE North

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2sv3 2 8 GiB 16 GiB $0.1254/hour $0.2215/hour

D4sv3 4 16 GiB 32 GiB $0.2508/hour $0.4431/hour

D8sv3 8 32 GiB 64 GiB $0.5016/hour $0.8862/hour

D16sv3 16 64 GiB 128 GiB $1.0032/hour $1.7723/hour

back to top
Brazil South

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2sv3 2 8 GiB 16 GiB $0.1662/hour $0.2623/hour

D4sv3 4 16 GiB 32 GiB $0.3323/hour $0.5246/hour

D8sv3 8 32 GiB 64 GiB $0.6646/hour $1.0492/hour

D16sv3 16 64 GiB 128 GiB $1.3292/hour $2.0984/hour

back to top
South Africa North
IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2sv3 2 8 GiB 16 GiB $0.1327/hour $0.2289/hour

D4sv3 4 16 GiB 32 GiB $0.2654/hour $0.4577/hour

D8sv3 8 32 GiB 64 GiB $0.5309/hour $0.9154/hour

D16sv3 16 64 GiB 128 GiB $1.0617/hour $1.8308/hour

back to top
Australia East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2sv3 2 8 GiB 16 GiB $0.1306/hour $0.2268/hour

D4sv3 4 16 GiB 32 GiB $0.2613/hour $0.4535/hour

D8sv3 8 32 GiB 64 GiB $0.5225/hour $0.9071/hour

D16sv3 16 64 GiB 128 GiB $1.045/hour $1.8141/hour

back to top
Australia South East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2sv3 2 8 GiB 16 GiB $0.1306/hour $0.2268/hour

D4sv3 4 16 GiB 32 GiB $0.2613/hour $0.4535/hour

D8sv3 8 32 GiB 64 GiB $0.5225/hour $0.9071/hour

D16sv3 16 64 GiB 128 GiB $1.045/hour $1.8141/hour

back to top
Korea Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2sv3 2 8 GiB 16 GiB $0.1285/hour $0.2247/hour

D4sv3 4 16 GiB 32 GiB $0.2571/hour $0.4493/hour

D8sv3 8 32 GiB 64 GiB $0.5141/hour $0.8987/hour

D16sv3 16 64 GiB 128 GiB $1.0283/hour $1.7974/hour

back to top
Japan East
IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2sv3 2 8 GiB 16 GiB $0.1348/hour $0.2309/hour

D4sv3 4 16 GiB 32 GiB $0.2696/hour $0.4619/hour

D8sv3 8 32 GiB 64 GiB $0.5392/hour $0.9238/hour

D16sv3 16 64 GiB 128 GiB $1.0784/hour $1.8476/hour

back to top
Japan West

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2sv3 2 8 GiB 16 GiB $0.1902/hour $0.2309/hour

D4sv3 4 16 GiB 32 GiB $0.3814/hour $0.4619/hour

D8sv3 8 32 GiB 64 GiB $0.7618/hour $0.9238/hour

D16sv3 16 64 GiB 128 GiB $1.5247/hour $1.8476/hour

back to top
East Asia

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2sv3 2 8 GiB 16 GiB $0.1379/hour $0.2341/hour

D4sv3 4 16 GiB 32 GiB $0.2759/hour $0.4682/hour

D8sv3 8 32 GiB 64 GiB $0.5518/hour $0.9363/hour

D16sv3 16 64 GiB 128 GiB $1.1035/hour $1.8726/hour

back to top
South East Asia

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2sv3 2 8 GiB 16 GiB $0.1306/hour $0.2268/hour

D4sv3 4 16 GiB 32 GiB $0.2613/hour $0.4535/hour

D8sv3 8 32 GiB 64 GiB $0.5225/hour $0.9071/hour

D16sv3 16 64 GiB 128 GiB $1.045/hour $1.8141/hour

Fv1
The F-series virtual machines feature 2-GiB RAM and 16 GiB of local SSD temporary storage per CPU core and
are optimized for compute intensive workloads. The F-series sizes are based Intel® Xeon® Platinum 8272CL
processor (second generation Intel® Xeon® Scalable processors), Intel® Xeon® 8171M 2.1GHz (Skylake),
Intel® Xeon® E5-2673 v4 2.3 GHz (Broadwell), or the Intel® Xeon® E5-2673 v3 2.4 GHz (Haswell)
processor. These virtual machines are suitable for scenarios like batch processing, web servers, analytics, and
gaming.
back to top
US East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2v1 2 4 GiB 32 GiB $0.1089/hour $0.2112/hour

F4v1 4 8 GiB 64 GiB $0.2189/hour $0.4213/hour

F8v1 8 16 GiB 128 GiB $0.4378/hour $0.8426/hour

F16v1 16 32 GiB 256 GiB $0.8756/hour $1.6852/hour

back to top
US East 2

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2v1 2 4 GiB 32 GiB $0.1089/hour $0.2112/hour

F4v1 4 8 GiB 64 GiB $0.2189/hour $0.4213/hour

F8v1 8 16 GiB 128 GiB $0.4378/hour $0.8426/hour

F16v1 16 32 GiB 256 GiB $0.8756/hour $1.6852/hour

back to top
US West

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2v1 2 4 GiB 32 GiB $0.1364/hour $0.2376/hour

F4v1 4 8 GiB 64 GiB $0.2739/hour $0.4763/hour

F8v1 8 16 GiB 128 GiB $0.5478/hour $0.9526/hour

F16v1 16 32 GiB 256 GiB $1.0956/hour $1.9052/hour

back to top
US West 2

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2v1 2 4 GiB 32 GiB $0.1089/hour $0.2112/hour

F4v1 4 8 GiB 64 GiB $0.2189/hour $0.4213/hour


IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F8v1 8 16 GiB 128 GiB $0.4378/hour $0.8426/hour

F16v1 16 32 GiB 256 GiB $0.8756/hour $1.6852/hour

back to top
US Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2v1 2 4 GiB 32 GiB $0.1199/hour $0.2321/hour

F4v1 4 8 GiB 64 GiB $0.2409/hour $0.4631/hour

F8v1 8 16 GiB 128 GiB $0.4818/hour $0.9262/hour

F16v1 16 32 GiB 256 GiB $0.9625/hour $1.8535/hour

back to top
US North Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2v1 2 4 GiB 32 GiB $0.1089/hour $0.2112/hour

F4v1 4 8 GiB 64 GiB $0.2189/hour $0.4213/hour

F8v1 8 16 GiB 128 GiB $0.4378/hour $0.8426/hour

F16v1 16 32 GiB 256 GiB $0.8756/hour $1.6852/hour

back to top
US South Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2v1 2 4 GiB 32 GiB $0.1199/hour $0.2255/hour

F4v1 4 8 GiB 64 GiB $0.2409/hour $0.4521/hour

F8v1 8 16 GiB 128 GiB $0.4818/hour $0.9042/hour

F16v1 16 32 GiB 256 GiB $0.9625/hour $1.8084/hour

back to top
US West Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2v1 2 4 GiB 32 GiB $0.1199/hour $0.2255/hour


IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F4v1 4 8 GiB 64 GiB $0.2409/hour $0.4521/hour

F8v1 8 16 GiB 128 GiB $0.4818/hour $0.9042/hour

F16v1 16 32 GiB 256 GiB $0.9625/hour $1.8084/hour

back to top
North Europe

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2v1 2 4 GiB 32 GiB $0.1243/hour $0.2244/hour

F4v1 4 8 GiB 64 GiB $0.2486/hour $0.4488/hour

F8v1 8 16 GiB 128 GiB $0.4972/hour $0.8976/hour

F16v1 16 32 GiB 256 GiB $0.9955/hour $1.7952/hour

back to top
West Europe

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2v1 2 4 GiB 32 GiB $0.1254/hour $0.2266/hour

F4v1 4 8 GiB 64 GiB $0.2497/hour $0.4521/hour

F8v1 8 16 GiB 128 GiB $0.4994/hour $0.9042/hour

F16v1 16 32 GiB 256 GiB $0.9999/hour $1.8095/hour

back to top
France Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2v1 2 4 GiB 32 GiB $0.1111/hour $0.2123/hour

F4v1 4 8 GiB 64 GiB $0.2222/hour $0.4246/hour

F8v1 8 16 GiB 128 GiB $0.4444/hour $0.8492/hour

F16v1 16 32 GiB 256 GiB $0.8888/hour $1.6984/hour

back to top
India Central
IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2v1 2 4 GiB 32 GiB $0.1087/hour $0.2112/hour

F4v1 4 8 GiB 64 GiB $0.2178/hour $0.4213/hour

F8v1 8 16 GiB 128 GiB $0.4345/hour $0.8426/hour

F16v1 16 32 GiB 256 GiB $0.869/hour $1.6852/hour

back to top
UAE North

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2v1 2 4 GiB 32 GiB $0.1309/hour $0.2321/hour

F4v1 4 8 GiB 64 GiB $0.2629/hour $0.4653/hour

F8v1 8 16 GiB 128 GiB $0.5258/hour $0.9306/hour

F16v1 16 32 GiB 256 GiB $1.0505/hour $1.8601/hour

back to top
Brazil South

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2v1 2 4 GiB 32 GiB $0.1584/hour $0.2442/hour

F4v1 4 8 GiB 64 GiB $0.3157/hour $0.4884/hour

F8v1 8 16 GiB 128 GiB $0.6314/hour $0.9757/hour

F16v1 16 32 GiB 256 GiB $1.2628/hour $1.9514/hour

back to top
South Africa North

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2v1 2 4 GiB 32 GiB $0.1463/hour $0.2475/hour

F4v1 4 8 GiB 64 GiB $0.2937/hour $0.4961/hour

F8v1 8 16 GiB 128 GiB $0.5863/hour $0.9911/hour

F16v1 16 32 GiB 256 GiB $1.1726/hour $1.9822/hour

back to top
Australia East
IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2v1 2 4 GiB 32 GiB $0.143/hour $0.2442/hour

F4v1 4 8 GiB 64 GiB $0.286/hour $0.4884/hour

F8v1 8 16 GiB 128 GiB $0.5731/hour $0.9779/hour

F16v1 16 32 GiB 256 GiB $1.1462/hour $1.9547/hour

back to top
Australia South East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2v1 2 4 GiB 32 GiB $0.143/hour $0.2442/hour

F4v1 4 8 GiB 64 GiB $0.286/hour $0.4884/hour

F8v1 8 16 GiB 128 GiB $0.5731/hour $0.9779/hour

F16v1 16 32 GiB 256 GiB $1.1462/hour $1.9547/hour

back to top
Korea Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2v1 2 4 GiB 32 GiB $0.1122/hour $0.2035/hour

F4v1 4 8 GiB 64 GiB $0.2244/hour $0.407/hour

F8v1 8 16 GiB 128 GiB $0.4488/hour $0.814/hour

F16v1 16 32 GiB 256 GiB $0.8976/hour $1.6269/hour

back to top
Japan East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2v1 2 4 GiB 32 GiB $0.1386/hour $0.2398/hour

F4v1 4 8 GiB 64 GiB $0.2772/hour $0.4796/hour

F8v1 8 16 GiB 128 GiB $0.5544/hour $0.9592/hour

F16v1 16 32 GiB 256 GiB $1.1088/hour $1.9184/hour

back to top
Japan West
IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2v1 2 4 GiB 32 GiB $0.1386/hour $0.2398/hour

F4v1 4 8 GiB 64 GiB $0.2772/hour $0.4796/hour

F8v1 8 16 GiB 128 GiB $0.5544/hour $0.9592/hour

F16v1 16 32 GiB 256 GiB $1.1088/hour $1.9184/hour

back to top
East Asia

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2v1 2 4 GiB 32 GiB $0.1584/hour $0.2849/hour

F4v1 4 8 GiB 64 GiB $0.3179/hour $0.5698/hour

F8v1 8 16 GiB 128 GiB $0.6358/hour $1.1396/hour

F16v1 16 32 GiB 256 GiB $1.2705/hour $2.2792/hour

back to top
South East Asia

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2v1 2 4 GiB 32 GiB $0.1265/hour $0.2277/hour

F4v1 4 8 GiB 64 GiB $0.2541/hour $0.4565/hour

F8v1 8 16 GiB 128 GiB $0.5082/hour $0.913/hour

F16v1 16 32 GiB 256 GiB $1.0164/hour $1.826/hour

Fsv2
The Fsv2-series virtual machines provide 2-GiB of RAM and 8 GB of local temporary storage (SSD) per vCPU(s)
and are optimized for compute intensive workloads. The Fsv2-series VMs are hyper-threaded and based on the
Intel® Xeon® Platinum 8272CL (second generation Intel® Xeon® Scalable processors), or the Intel
Xeon® Platinum 8168 (Skylake) processor. These virtual machines are ideal for scenarios like batch processing,
web servers, analytics, and gaming.
back to top
US East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2sv2 2 4 GiB 16 GiB $0.0884/hour $0.1703/hour

F4sv2 4 8 GiB 32 GiB $0.1766/hour $0.3407/hour


IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F8sv2 8 16 GiB 64 GiB $0.3532/hour $0.6803/hour

F16sv2 16 32 GiB 128 GiB $0.7075/hour $1.3606/hour

back to top
US East 2

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2sv2 2 4 GiB 16 GiB $0.0884/hour $0.1703/hour

F4sv2 4 8 GiB 32 GiB $0.1766/hour $0.3407/hour

F8sv2 8 16 GiB 64 GiB $0.3532/hour $0.6803/hour

F16sv2 16 32 GiB 128 GiB $0.7075/hour $1.3606/hour

back to top
US West

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2sv2 2 4 GiB 16 GiB $0.1108/hour $0.2069/hour

F4sv2 4 8 GiB 32 GiB $0.2215/hour $0.4138/hour

F8sv2 8 16 GiB 64 GiB $0.4431/hour $0.8276/hour

F16sv2 16 32 GiB 128 GiB $0.8862/hour $1.6553/hour

back to top
US West 2

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2sv2 2 4 GiB 16 GiB $0.0884/hour $0.1703/hour

F4sv2 4 8 GiB 32 GiB $0.1766/hour $0.3407/hour

F8sv2 8 16 GiB 64 GiB $0.3532/hour $0.6803/hour

F16sv2 16 32 GiB 128 GiB $0.7075/hour $1.3606/hour

back to top
US Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2sv2 2 4 GiB 16 GiB $0.1066/hour $0.2027/hour


IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F4sv2 4 8 GiB 32 GiB $0.2132/hour $0.4055/hour

F8sv2 8 16 GiB 64 GiB $0.4264/hour $0.8109/hour

F16sv2 16 32 GiB 128 GiB $0.8527/hour $1.6218/hour

back to top
US North Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2sv2 2 4 GiB 16 GiB $0.0888/hour $0.185/hour

F4sv2 4 8 GiB 32 GiB $0.1777/hour $0.3699/hour

F8sv2 8 16 GiB 64 GiB $0.3553/hour $0.7399/hour

F16sv2 16 32 GiB 128 GiB $0.7106/hour $1.4797/hour

back to top
US South Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2sv2 2 4 GiB 16 GiB $0.1066/hour $0.2027/hour

F4sv2 4 8 GiB 32 GiB $0.2132/hour $0.4055/hour

F8sv2 8 16 GiB 64 GiB $0.4264/hour $0.8109/hour

F16sv2 16 32 GiB 128 GiB $0.8527/hour $1.6218/hour

back to top
US West Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2sv2 2 4 GiB 16 GiB $0.1066/hour $0.2027/hour

F4sv2 4 8 GiB 32 GiB $0.2132/hour $0.4055/hour

F8sv2 8 16 GiB 64 GiB $0.4264/hour $0.8109/hour

F16sv2 16 32 GiB 128 GiB $0.8527/hour $1.6218/hour

back to top
North Europe
IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2sv2 2 4 GiB 16 GiB $0.1003/hour $0.1965/hour

F4sv2 4 8 GiB 32 GiB $0.2006/hour $0.3929/hour

F8sv2 8 16 GiB 64 GiB $0.4013/hour $0.7858/hour

F16sv2 16 32 GiB 128 GiB $0.8026/hour $1.5717/hour

back to top
West Europe

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2sv2 2 4 GiB 16 GiB $0.1014/hour $0.1933/hour

F4sv2 4 8 GiB 32 GiB $0.2027/hour $0.3866/hour

F8sv2 8 16 GiB 64 GiB $0.4055/hour $0.7733/hour

F16sv2 16 32 GiB 128 GiB $0.8109/hour $1.5476/hour

back to top
France Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2sv2 2 4 GiB 16 GiB $0.1055/hour $0.2017/hour

F4sv2 4 8 GiB 32 GiB $0.2111/hour $0.4034/hour

F8sv2 8 16 GiB 64 GiB $0.4222/hour $0.8067/hour

F16sv2 16 32 GiB 128 GiB $0.8444/hour $1.6135/hour

back to top
India Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2sv2 2 4 GiB 16 GiB $0.0888/hour $0.185/hour

F4sv2 4 8 GiB 32 GiB $0.1777/hour $0.3699/hour

F8sv2 8 16 GiB 64 GiB $0.3553/hour $0.7399/hour

F16sv2 16 32 GiB 128 GiB $0.7106/hour $1.4797/hour

back to top
UAE North
IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2sv2 2 4 GiB 16 GiB $0.1066/hour $0.2027/hour

F4sv2 4 8 GiB 32 GiB $0.2132/hour $0.4055/hour

F8sv2 8 16 GiB 64 GiB $0.4264/hour $0.8109/hour

F16sv2 16 32 GiB 128 GiB $0.8527/hour $1.6218/hour

back to top
Brazil South

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2sv2 2 4 GiB 16 GiB $0.1369/hour $0.233/hour

F4sv2 4 8 GiB 32 GiB $0.2738/hour $0.4661/hour

F8sv2 8 16 GiB 64 GiB $0.5476/hour $0.9321/hour

F16sv2 16 32 GiB 128 GiB $1.0952/hour $1.8643/hour

back to top
South Africa North

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2sv2 2 4 GiB 16 GiB $0.1191/hour $0.2153/hour

F4sv2 4 8 GiB 32 GiB $0.2383/hour $0.4305/hour

F8sv2 8 16 GiB 64 GiB $0.4765/hour $0.8611/hour

F16sv2 16 32 GiB 128 GiB $0.952/hour $1.7211/hour

back to top
Australia East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2sv2 2 4 GiB 16 GiB $0.116/hour $0.2121/hour

F4sv2 4 8 GiB 32 GiB $0.232/hour $0.4243/hour

F8sv2 8 16 GiB 64 GiB $0.464/hour $0.8485/hour

F16sv2 16 32 GiB 128 GiB $0.928/hour $1.6971/hour

back to top
Australia South East
IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2sv2 2 4 GiB 16 GiB $0.116/hour $0.2121/hour

F4sv2 4 8 GiB 32 GiB $0.233/hour $0.4253/hour

F8sv2 8 16 GiB 64 GiB $0.465/hour $0.8496/hour

F16sv2 16 32 GiB 128 GiB $0.9311/hour $1.7002/hour

back to top
Korea Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2sv2 2 4 GiB 16 GiB $0.1003/hour $0.1965/hour

F4sv2 4 8 GiB 32 GiB $0.2006/hour $0.3929/hour

F8sv2 8 16 GiB 64 GiB $0.4013/hour $0.7858/hour

F16sv2 16 32 GiB 128 GiB $0.8026/hour $1.5717/hour

back to top
Japan East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2sv2 2 4 GiB 16 GiB $0.1118/hour $0.208/hour

F4sv2 4 8 GiB 32 GiB $0.2236/hour $0.4159/hour

F8sv2 8 16 GiB 64 GiB $0.4473/hour $0.8318/hour

F16sv2 16 32 GiB 128 GiB $0.8945/hour $1.6636/hour

back to top
Japan West

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2sv2 2 4 GiB 16 GiB $0.1223/hour $0.2184/hour

F4sv2 4 8 GiB 32 GiB $0.2456/hour $0.4379/hour

F8sv2 8 16 GiB 64 GiB $0.4901/hour $0.8747/hour

F16sv2 16 32 GiB 128 GiB $0.9802/hour $1.7493/hour

back to top
East Asia
IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2sv2 2 4 GiB 16 GiB $0.1129/hour $0.209/hour

F4sv2 4 8 GiB 32 GiB $0.2257/hour $0.418/hour

F8sv2 8 16 GiB 64 GiB $0.4514/hour $0.836/hour

F16sv2 16 32 GiB 128 GiB $0.9029/hour $1.672/hour

back to top
South East Asia

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

F2sv2 2 4 GiB 16 GiB $0.1024/hour $0.1839/hour

F4sv2 4 8 GiB 32 GiB $0.2048/hour $0.3689/hour

F8sv2 8 16 GiB 64 GiB $0.4096/hour $0.7378/hour

F16sv2 16 32 GiB 128 GiB $0.8193/hour $1.4745/hour

Dav4
The Das v4-series VMs support Premium SSD disk storage and are based on the 2.35Ghz AMD EPYCTM 7452
processor, which can achieve up to 3.35GHz. The Das v4 VM sizes offer a combination of vCPUs, memory and
temporary storage able to meet the requirements associated with most production workloads.
back to top
US East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2av4 2 8 GiB 50 GiB $0.1056/hour $0.2068/hour

D4av4 4 16 GiB 100 GiB $0.2112/hour $0.4136/hour

D8av4 8 32 GiB 200 GiB $0.4224/hour $0.8272/hour

D16av4 16 64 GiB 400 GiB $0.8448/hour $1.6544/hour

back to top
US East 2

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2av4 2 8 GiB 50 GiB $0.1056/hour $0.2068/hour

D4av4 4 16 GiB 100 GiB $0.2112/hour $0.4136/hour

D8av4 8 32 GiB 200 GiB $0.4224/hour $0.8272/hour


IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D16av4 16 64 GiB 400 GiB $0.8448/hour $1.6544/hour

back to top
US West

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2av4 2 8 GiB 50 GiB $0.1232/hour $0.2244/hour

D4av4 4 16 GiB 100 GiB $0.2464/hour $0.4488/hour

D8av4 8 32 GiB 200 GiB $0.4928/hour $0.8976/hour

D16av4 16 64 GiB 400 GiB $0.9856/hour $1.7952/hour

back to top
US West 2

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2av4 2 8 GiB 50 GiB $0.1056/hour $0.2068/hour

D4av4 4 16 GiB 100 GiB $0.2112/hour $0.4136/hour

D8av4 8 32 GiB 200 GiB $0.4224/hour $0.8272/hour

D16av4 16 64 GiB 400 GiB $0.8448/hour $1.6544/hour

back to top
US Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2av4 2 8 GiB 50 GiB $0.1188/hour $0.22/hour

D4av4 4 16 GiB 100 GiB $0.2387/hour $0.4411/hour

D8av4 8 32 GiB 200 GiB $0.4774/hour $0.8822/hour

D16av4 16 64 GiB 400 GiB $0.9548/hour $1.7644/hour

back to top
US North Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2av4 2 8 GiB 50 GiB $0.1265/hour $0.2277/hour

D4av4 4 16 GiB 100 GiB $0.253/hour $0.4554/hour


IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D8av4 8 32 GiB 200 GiB $0.5071/hour $0.9119/hour

D16av4 16 64 GiB 400 GiB $1.0142/hour $1.8238/hour

back to top
US South Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2av4 2 8 GiB 50 GiB $0.1265/hour $0.2277/hour

D4av4 4 16 GiB 100 GiB $0.253/hour $0.4554/hour

D8av4 8 32 GiB 200 GiB $0.5071/hour $0.9119/hour

D16av4 16 64 GiB 400 GiB $1.0142/hour $1.8238/hour

back to top
US West Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

back to top
North Europe

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2av4 2 8 GiB 50 GiB $0.1177/hour $0.2189/hour

D4av4 4 16 GiB 100 GiB $0.2354/hour $0.4378/hour

D8av4 8 32 GiB 200 GiB $0.4708/hour $0.8756/hour

D16av4 16 64 GiB 400 GiB $0.9416/hour $1.7512/hour

back to top
West Europe

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2av4 2 8 GiB 50 GiB $0.1265/hour $0.2277/hour

D4av4 4 16 GiB 100 GiB $0.253/hour $0.4554/hour

D8av4 8 32 GiB 200 GiB $0.506/hour $0.9108/hour

D16av4 16 64 GiB 400 GiB $1.012/hour $1.8216/hour

back to top
France Central
IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

back to top
India Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2av4 2 8 GiB 50 GiB $0.0684/hour $0.1808/hour

D4av4 4 16 GiB 100 GiB $0.1356/hour $0.3606/hour

D8av4 8 32 GiB 200 GiB $0.2714/hour $0.7212/hour

D16av4 16 64 GiB 400 GiB $0.5426/hour $1.4422/hour

back to top
UAE North

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

back to top
Brazil South

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2av4 2 8 GiB 50 GiB $0.1683/hour $0.2695/hour

D4av4 4 16 GiB 100 GiB $0.3366/hour $0.539/hour

D8av4 8 32 GiB 200 GiB $0.6732/hour $1.078/hour

D16av4 16 64 GiB 400 GiB $1.3464/hour $2.156/hour

back to top
South Africa North

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

back to top
Australia East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2av4 2 8 GiB 50 GiB $0.132/hour $0.2332/hour

D4av4 4 16 GiB 100 GiB $0.264/hour $0.4664/hour

D8av4 8 32 GiB 200 GiB $0.528/hour $0.9328/hour

D16av4 16 64 GiB 400 GiB $1.056/hour $1.8656/hour

back to top
Australia South East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

back to top
Korea Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2av4 2 8 GiB 50 GiB $0.1298/hour $0.231/hour

D4av4 4 16 GiB 100 GiB $0.2596/hour $0.462/hour

D8av4 8 32 GiB 200 GiB $0.5192/hour $0.924/hour

D16av4 16 64 GiB 400 GiB $1.0384/hour $1.848/hour

back to top
Japan East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2av4 2 8 GiB 50 GiB $0.1364/hour $0.2376/hour

D4av4 4 16 GiB 100 GiB $0.2728/hour $0.4752/hour

D8av4 8 32 GiB 200 GiB $0.5456/hour $0.9504/hour

D16av4 16 64 GiB 400 GiB $1.0912/hour $1.9008/hour

back to top
Japan West

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

back to top
East Asia

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2av4 2 8 GiB 50 GiB $0.1452/hour $0.2464/hour

D4av4 4 16 GiB 100 GiB $0.2904/hour $0.4928/hour

D8av4 8 32 GiB 200 GiB $0.5808/hour $0.9856/hour

D16av4 16 64 GiB 400 GiB $1.1616/hour $1.9712/hour

back to top
South East Asia
IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2av4 2 8 GiB 50 GiB $0.132/hour $0.2332/hour

D4av4 4 16 GiB 100 GiB $0.264/hour $0.4664/hour

D8av4 8 32 GiB 200 GiB $0.528/hour $0.9328/hour

D16av4 16 64 GiB 400 GiB $1.056/hour $1.8656/hour

Dasv4
The Da v4-series VMs are based on the 2.35Ghz AMD EPYCTM 7452 processor, which can achieve up to
3.35GHz. The Dav4 VM sizes offer a combination of vCPU(s), memory and temporary storage able to meet the
requirements associated with most production workloads. Data disk storage is billed separately from virtual
machines. To use Premium SSD disk storage, select the Das v4 VMs.
back to top
US East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2asv4 2 8 GiB 16 GiB $0.1003/hour $0.1965/hour

D4asv4 4 16 GiB 32 GiB $0.2006/hour $0.3929/hour

D8asv4 8 32 GiB 64 GiB $0.4013/hour $0.7858/hour

D16asv4 16 64 GiB 128 GiB $0.8026/hour $1.5717/hour

back to top
US East 2

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2asv4 2 8 GiB 16 GiB $0.1003/hour $0.1965/hour

D4asv4 4 16 GiB 32 GiB $0.2006/hour $0.3929/hour

D8asv4 8 32 GiB 64 GiB $0.4013/hour $0.7858/hour

D16asv4 16 64 GiB 128 GiB $0.8026/hour $1.5717/hour

back to top
US West

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2asv4 2 8 GiB 16 GiB $0.117/hour $0.2132/hour

D4asv4 4 16 GiB 32 GiB $0.2341/hour $0.4264/hour

D8asv4 8 32 GiB 64 GiB $0.4682/hour $0.8527/hour


IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D16asv4 16 64 GiB 128 GiB $0.9363/hour $1.7054/hour

back to top
US West 2

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2asv4 2 8 GiB 16 GiB $0.1003/hour $0.1965/hour

D4asv4 4 16 GiB 32 GiB $0.2006/hour $0.3929/hour

D8asv4 8 32 GiB 64 GiB $0.4013/hour $0.7858/hour

D16asv4 16 64 GiB 128 GiB $0.8026/hour $1.5717/hour

back to top
US Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2asv4 2 8 GiB 16 GiB $0.1129/hour $0.209/hour

D4asv4 4 16 GiB 32 GiB $0.2268/hour $0.419/hour

D8asv4 8 32 GiB 64 GiB $0.4535/hour $0.8381/hour

D16asv4 16 64 GiB 128 GiB $0.9071/hour $1.6762/hour

back to top
US North Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2asv4 2 8 GiB 16 GiB $0.1202/hour $0.2163/hour

D4asv4 4 16 GiB 32 GiB $0.2404/hour $0.4326/hour

D8asv4 8 32 GiB 64 GiB $0.4817/hour $0.8663/hour

D16asv4 16 64 GiB 128 GiB $0.9635/hour $1.7326/hour

back to top
US South Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2asv4 2 8 GiB 16 GiB $0.1202/hour $0.2163/hour

D4asv4 4 16 GiB 32 GiB $0.2404/hour $0.4326/hour


IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D8asv4 8 32 GiB 64 GiB $0.4817/hour $0.8663/hour

D16asv4 16 64 GiB 128 GiB $0.9635/hour $1.7326/hour

back to top
US West Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

back to top
North Europe

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2asv4 2 8 GiB 16 GiB $0.1118/hour $0.208/hour

D4asv4 4 16 GiB 32 GiB $0.2236/hour $0.4159/hour

D8asv4 8 32 GiB 64 GiB $0.4473/hour $0.8318/hour

D16asv4 16 64 GiB 128 GiB $0.8945/hour $1.6636/hour

back to top
West Europe

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2asv4 2 8 GiB 16 GiB $0.1202/hour $0.2163/hour

D4asv4 4 16 GiB 32 GiB $0.2404/hour $0.4326/hour

D8asv4 8 32 GiB 64 GiB $0.4807/hour $0.8653/hour

D16asv4 16 64 GiB 128 GiB $0.9614/hour $1.7305/hour

back to top
France Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

back to top
India Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2asv4 2 8 GiB 16 GiB $0.065/hour $0.1718/hour

D4asv4 4 16 GiB 32 GiB $0.1288/hour $0.3426/hour

D8asv4 8 32 GiB 64 GiB $0.2578/hour $0.6851/hour


IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D16asv4 16 64 GiB 128 GiB $0.5155/hour $1.3701/hour

back to top
UAE North

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

back to top
Brazil South

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2asv4 2 8 GiB 16 GiB $0.1599/hour $0.256/hour

D4asv4 4 16 GiB 32 GiB $0.3198/hour $0.5121/hour

D8asv4 8 32 GiB 64 GiB $0.6395/hour $1.0241/hour

D16asv4 16 64 GiB 128 GiB $1.2791/hour $2.0482/hour

back to top
South Africa North

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

back to top
Australia East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2asv4 2 8 GiB 16 GiB $0.1254/hour $0.2215/hour

D4asv4 4 16 GiB 32 GiB $0.2508/hour $0.4431/hour

D8asv4 8 32 GiB 64 GiB $0.5016/hour $0.8862/hour

D16asv4 16 64 GiB 128 GiB $1.0032/hour $1.7723/hour

back to top
Australia South East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

back to top
Korea Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2asv4 2 8 GiB 16 GiB $0.1233/hour $0.2194/hour


IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D4asv4 4 16 GiB 32 GiB $0.2466/hour $0.4389/hour

D8asv4 8 32 GiB 64 GiB $0.4932/hour $0.8778/hour

D16asv4 16 64 GiB 128 GiB $0.9865/hour $1.7556/hour

back to top
Japan East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2asv4 2 8 GiB 16 GiB $0.1296/hour $0.2257/hour

D4asv4 4 16 GiB 32 GiB $0.2592/hour $0.4514/hour

D8asv4 8 32 GiB 64 GiB $0.5183/hour $0.9029/hour

D16asv4 16 64 GiB 128 GiB $1.0366/hour $1.8058/hour

back to top
Japan West

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

back to top
East Asia

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2asv4 2 8 GiB 16 GiB $0.1379/hour $0.2341/hour

D4asv4 4 16 GiB 32 GiB $0.2759/hour $0.4682/hour

D8asv4 8 32 GiB 64 GiB $0.5518/hour $0.9363/hour

D16asv4 16 64 GiB 128 GiB $1.1035/hour $1.8726/hour

back to top
South East Asia

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

D2asv4 2 8 GiB 16 GiB $0.1254/hour $0.2215/hour

D4asv4 4 16 GiB 32 GiB $0.2508/hour $0.4431/hour

D8asv4 8 32 GiB 64 GiB $0.5016/hour $0.8862/hour

D16asv4 16 64 GiB 128 GiB $1.0032/hour $1.7723/hour


Eav4
The Ea v4-series VMs are based on the 2.35Ghz AMD EPYCTM 7452 processor, which can achieve up to
3.35GHz. The Ea v4-series VMs are ideal for memory-intensive enterprise applications. Data disk storage is
billed separately from virtual machines.
back to top
US East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E2av4 2 16 GiB 50 GiB $0.1386/hour $0.2398/hour

E4av4 4 32 GiB 100 GiB $0.2772/hour $0.4796/hour

E8av4 8 64 GiB 200 GiB $0.5544/hour $0.9592/hour

E16av4 16 128 GiB 400 GiB $1.1088/hour $1.9184/hour

back to top
US East 2

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E2av4 2 16 GiB 50 GiB $0.1386/hour $0.2398/hour

E4av4 4 32 GiB 100 GiB $0.2772/hour $0.4796/hour

E8av4 8 64 GiB 200 GiB $0.5544/hour $0.9592/hour

E16av4 16 128 GiB 400 GiB $1.1088/hour $1.9184/hour

back to top
US West

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E2av4 2 16 GiB 50 GiB $0.154/hour $0.2552/hour

E4av4 4 32 GiB 100 GiB $0.308/hour $0.5104/hour

E8av4 8 64 GiB 200 GiB $0.616/hour $1.0208/hour

E16av4 16 128 GiB 400 GiB $1.232/hour $2.0416/hour

back to top
US West 2

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E2av4 2 16 GiB 50 GiB $0.1386/hour $0.2398/hour

E4av4 4 32 GiB 100 GiB $0.2772/hour $0.4796/hour


IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E8av4 8 64 GiB 200 GiB $0.5544/hour $0.9592/hour

E16av4 16 128 GiB 400 GiB $1.1088/hour $1.9184/hour

back to top
US Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E2av4 2 16 GiB 50 GiB $0.1562/hour $0.2574/hour

E4av4 4 32 GiB 100 GiB $0.3135/hour $0.5159/hour

E8av4 8 64 GiB 200 GiB $0.627/hour $1.0318/hour

E16av4 16 128 GiB 400 GiB $1.2529/hour $2.0625/hour

back to top
US North Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E2av4 2 16 GiB 50 GiB $0.1661/hour $0.2673/hour

E4av4 4 32 GiB 100 GiB $0.3322/hour $0.5346/hour

E8av4 8 64 GiB 200 GiB $0.6655/hour $1.0703/hour

E16av4 16 128 GiB 400 GiB $1.331/hour $2.1406/hour

back to top
US South Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E2av4 2 16 GiB 50 GiB $0.1661/hour $0.2673/hour

E4av4 4 32 GiB 100 GiB $0.3322/hour $0.5346/hour

E8av4 8 64 GiB 200 GiB $0.6655/hour $1.0703/hour

E16av4 16 128 GiB 400 GiB $1.331/hour $2.1406/hour

back to top
US West Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

back to top
North Europe
IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E2av4 2 16 GiB 50 GiB $0.1551/hour $0.2563/hour

E4av4 4 32 GiB 100 GiB $0.3102/hour $0.5126/hour

E8av4 8 64 GiB 200 GiB $0.6204/hour $1.0252/hour

E16av4 16 128 GiB 400 GiB $1.2408/hour $2.0504/hour

back to top
West Europe

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E2av4 2 16 GiB 50 GiB $0.1672/hour $0.2684/hour

E4av4 4 32 GiB 100 GiB $0.3344/hour $0.5368/hour

E8av4 8 64 GiB 200 GiB $0.6688/hour $1.0736/hour

E16av4 16 128 GiB 400 GiB $1.3376/hour $2.1472/hour

back to top
France Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

back to top
India Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E2av4 2 16 GiB 50 GiB $0.088/hour $0.2004/hour

E4av4 4 32 GiB 100 GiB $0.1748/hour $0.3996/hour

E8av4 8 64 GiB 200 GiB $0.3496/hour $0.7994/hour

E16av4 16 128 GiB 400 GiB $0.6992/hour $1.5986/hour

back to top
UAE North

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

back to top
Brazil South

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E2av4 2 16 GiB 50 GiB $0.2211/hour $0.3223/hour


IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E4av4 4 32 GiB 100 GiB $0.4422/hour $0.6446/hour

E8av4 8 64 GiB 200 GiB $0.8844/hour $1.2892/hour

E16av4 16 128 GiB 400 GiB $1.7688/hour $2.5784/hour

back to top
South Africa North

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

back to top
Australia East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E2av4 2 16 GiB 50 GiB $0.1661/hour $0.2673/hour

E4av4 4 32 GiB 100 GiB $0.3322/hour $0.5346/hour

E8av4 8 64 GiB 200 GiB $0.6644/hour $1.0692/hour

E16av4 16 128 GiB 400 GiB $1.3288/hour $2.1384/hour

back to top
Australia South East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

back to top
Korea Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E2av4 2 16 GiB 50 GiB $0.1672/hour $0.2684/hour

E4av4 4 32 GiB 100 GiB $0.3344/hour $0.5368/hour

E8av4 8 64 GiB 200 GiB $0.6688/hour $1.0736/hour

E16av4 16 128 GiB 400 GiB $1.3376/hour $2.1472/hour

back to top
Japan East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E2av4 2 16 GiB 50 GiB $0.1672/hour $0.2684/hour

E4av4 4 32 GiB 100 GiB $0.3344/hour $0.5368/hour


IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E8av4 8 64 GiB 200 GiB $0.6688/hour $1.0736/hour

E16av4 16 128 GiB 400 GiB $1.3376/hour $2.1472/hour

back to top
Japan West

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

back to top
East Asia

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E2av4 2 16 GiB 50 GiB $0.1837/hour $0.2849/hour

E4av4 4 32 GiB 100 GiB $0.3674/hour $0.5698/hour

E8av4 8 64 GiB 200 GiB $0.7348/hour $1.1396/hour

E16av4 16 128 GiB 400 GiB $1.4696/hour $2.2792/hour

back to top
South East Asia

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E2av4 2 16 GiB 50 GiB $0.1672/hour $0.2684/hour

E4av4 4 32 GiB 100 GiB $0.3344/hour $0.5368/hour

E8av4 8 64 GiB 200 GiB $0.6688/hour $1.0736/hour

E16av4 16 128 GiB 400 GiB $1.3376/hour $2.1472/hour

Easv4
The Eas v4-series VMs support Premium SSD disk storage and are based on the 2.35Ghz AMD EPYCTM 7452
processor, which can achieve up to 3.35GHz. The Eas v4-series VMs are ideal for memory-intensive enterprise
applications.
back to top
US East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E2asv4 2 16 GiB 32 GiB $0.1317/hour $0.2278/hour

E4asv4 4 32 GiB 64 GiB $0.2633/hour $0.4556/hour

E8asv4 8 64 GiB 128 GiB $0.5267/hour $0.9112/hour


IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E16asv4 16 128 GiB 256 GiB $1.0534/hour $1.8225/hour

back to top
US East 2

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E2asv4 2 16 GiB 32 GiB $0.1317/hour $0.2278/hour

E4asv4 4 32 GiB 64 GiB $0.2633/hour $0.4556/hour

E8asv4 8 64 GiB 128 GiB $0.5267/hour $0.9112/hour

E16asv4 16 128 GiB 256 GiB $1.0534/hour $1.8225/hour

back to top
US West

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E2asv4 2 16 GiB 32 GiB $0.1463/hour $0.2424/hour

E4asv4 4 32 GiB 64 GiB $0.2926/hour $0.4849/hour

E8asv4 8 64 GiB 128 GiB $0.5852/hour $0.9698/hour

E16asv4 16 128 GiB 256 GiB $1.1704/hour $1.9395/hour

back to top
US West 2

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E2asv4 2 16 GiB 32 GiB $0.1317/hour $0.2278/hour

E4asv4 4 32 GiB 64 GiB $0.2633/hour $0.4556/hour

E8asv4 8 64 GiB 128 GiB $0.5267/hour $0.9112/hour

E16asv4 16 128 GiB 256 GiB $1.0534/hour $1.8225/hour

back to top
US Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E2asv4 2 16 GiB 32 GiB $0.1484/hour $0.2445/hour

E4asv4 4 32 GiB 64 GiB $0.2978/hour $0.4901/hour


IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E8asv4 8 64 GiB 128 GiB $0.5957/hour $0.9802/hour

E16asv4 16 128 GiB 256 GiB $1.1903/hour $1.9594/hour

back to top
US North Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E2asv4 2 16 GiB 32 GiB $0.1578/hour $0.2539/hour

E4asv4 4 32 GiB 64 GiB $0.3156/hour $0.5079/hour

E8asv4 8 64 GiB 128 GiB $0.6322/hour $1.0168/hour

E16asv4 16 128 GiB 256 GiB $1.2645/hour $2.0336/hour

back to top
US South Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E2asv4 2 16 GiB 32 GiB $0.1578/hour $0.2539/hour

E4asv4 4 32 GiB 64 GiB $0.3156/hour $0.5079/hour

E8asv4 8 64 GiB 128 GiB $0.6322/hour $1.0168/hour

E16asv4 16 128 GiB 256 GiB $1.2645/hour $2.0336/hour

back to top
US West Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

back to top
North Europe

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E2asv4 2 16 GiB 32 GiB $0.1473/hour $0.2435/hour

E4asv4 4 32 GiB 64 GiB $0.2947/hour $0.487/hour

E8asv4 8 64 GiB 128 GiB $0.5894/hour $0.9739/hour

E16asv4 16 128 GiB 256 GiB $1.1788/hour $1.9479/hour

back to top
West Europe
IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E2asv4 2 16 GiB 32 GiB $0.1588/hour $0.255/hour

E4asv4 4 32 GiB 64 GiB $0.3177/hour $0.51/hour

E8asv4 8 64 GiB 128 GiB $0.6354/hour $1.0199/hour

E16asv4 16 128 GiB 256 GiB $1.2707/hour $2.0398/hour

back to top
France Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

back to top
India Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E2asv4 2 16 GiB 32 GiB $0.0836/hour $0.1904/hour

E4asv4 4 32 GiB 64 GiB $0.1661/hour $0.3796/hour

E8asv4 8 64 GiB 128 GiB $0.3321/hour $0.7594/hour

E16asv4 16 128 GiB 256 GiB $0.6642/hour $1.5187/hour

back to top
UAE North

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

back to top
Brazil South

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E2asv4 2 16 GiB 32 GiB $0.21/hour $0.3062/hour

E4asv4 4 32 GiB 64 GiB $0.4201/hour $0.6124/hour

E8asv4 8 64 GiB 128 GiB $0.8402/hour $1.2247/hour

E16asv4 16 128 GiB 256 GiB $1.6804/hour $2.4495/hour

back to top
South Africa North

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

back to top
Australia East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E2asv4 2 16 GiB 32 GiB $0.1578/hour $0.2539/hour

E4asv4 4 32 GiB 64 GiB $0.3156/hour $0.5079/hour

E8asv4 8 64 GiB 128 GiB $0.6312/hour $1.0157/hour

E16asv4 16 128 GiB 256 GiB $1.2624/hour $2.0315/hour

back to top
Australia South East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

back to top
Korea Central

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E2asv4 2 16 GiB 32 GiB $0.1588/hour $0.255/hour

E4asv4 4 32 GiB 64 GiB $0.3177/hour $0.51/hour

E8asv4 8 64 GiB 128 GiB $0.6354/hour $1.0199/hour

E16asv4 16 128 GiB 256 GiB $1.2707/hour $2.0398/hour

back to top
Japan East

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E2asv4 2 16 GiB 32 GiB $0.1588/hour $0.255/hour

E4asv4 4 32 GiB 64 GiB $0.3177/hour $0.51/hour

E8asv4 8 64 GiB 128 GiB $0.6354/hour $1.0199/hour

E16asv4 16 128 GiB 256 GiB $1.2707/hour $2.0398/hour

back to top
Japan West

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

back to top
East Asia
IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E2asv4 2 16 GiB 32 GiB $0.1745/hour $0.2707/hour

E4asv4 4 32 GiB 64 GiB $0.349/hour $0.5413/hour

E8asv4 8 64 GiB 128 GiB $0.6981/hour $1.0826/hour

E16asv4 16 128 GiB 256 GiB $1.3961/hour $2.1652/hour

back to top
South East Asia

IN STA N C E VC P U RA M STO RA GE L IN UX W IN DO W S

E2asv4 2 16 GiB 32 GiB $0.1588/hour $0.255/hour

E4asv4 4 32 GiB 64 GiB $0.3177/hour $0.51/hour

E8asv4 8 64 GiB 128 GiB $0.6354/hour $1.0199/hour

E16asv4 16 128 GiB 256 GiB $1.2707/hour $2.0398/hour

Network egress price by zone


ZONE REGIO N S $/ GB O F N ET W O RK EGRESS

Zone 1 US East, West, Central, North Europe, $0.05


West Europe, France Central

Zone 2 East Asia, South East Asia, Australia $0.08


East, Australia South East

Zone 3 UAE North, India Central, South Africa $0.20


North, Brazil South
PlayFab incident response procedures
5/24/2022 • 2 minutes to read • Edit Online

PlayFab is committed to the reliable operation of our services 24/7. However, incidents do occur. This page
describes how you can raise incidents to our attention and how PlayFab communicates our status during
incident mitigation.

Paging PlayFab
If you are a PlayFab enterprise customer, you will have been provided a confidential email address to alert us to
any urgent issues. This email inbox pages our engineering team 24/7, and you will be provided an
acknowledgement within 30 minutes of email receipt.

Ongoing communication of incidents


PlayFab’s communication procedures vary depending on the severity of the incident. The taxonomy we use to
assess incident severity is shown in the table below:

SEVERIT Y P L AY FA B STAT US L A B EL DESC RIP T IO N RESP O N SE EXP EC TAT IO N

1 Critical Critial outage across Worked 24x7 until resolved.


multiple systems. These are Initial Response in 15
exceptionally rare outages minutes or less. External
that impact multiple Communication in <20
PlayFab systems and a wide minutes.
swatch of player activity. For
example, an inability to log-
in or create entity tokens.

2 Major These outages impact a Worked 24x7 until resolved.


limited set of PlayFab sub- Initial Response in 15
systems but are causing minutess or less. External
player-facing impact for a Communication in <20
wide swatch of customers. minutes.

3 Degradation These incidents are Worked 24x7 until resolved.


impacting players but are Initial Response in 30
limited to a specific region minutes or less. External
or not typically fatal to the Communication in <60
gameplay experience. minutes.

NOTE
The Status Labels listed in the table are the ones used on our System Status site status.playfab.com.

Severity 1 and 2 outages will be reported as a Major Outage on status.playfab.com. On-going updates will be
provided every 30 minutes through status.playfab.com, Slack, and Teams.
Severity 3 outages will be reported as a Degradation on status.playfab.com, with on-going updates every 60
minutes. These incidents are not communicated through Slack or Teams.
In some cases, PlayFab may detect that a Severity 2 or Severity 3 outage is occurring but only impacting one or
two titles. In these situations, we will not post to status.playfab.com. Instead, we will post to your specific Slack or
Teams channel and provide updates every 30-60 minutes.
Managing server capacity
5/24/2022 • 4 minutes to read • Edit Online

A game servers' ability to scale in response to player demand is dependent on the number of simultaneous
virtual machine cores consumed by a multiplayer server game. If a game server runs out of VM cores,
subsequent requests to allocate VMs will fail. Monitoring server capacity is essential to prevent capacity errors
or diagnosing scaling problems due to player demand. This article describes the Quota Usage page and how to
manage your game server for capacity issues.
To access the quota usage page, navigate to the Multiplayer | Servers | Quota menu. The Quota Usage page
surfaces peak core usage both in visualized charts and a tabulated format. The data powering these metrics is
sampled every 60 minutes.

Monitoring peak core usage per region


At the top of the quota usage page is a chart that visualizes peak core usage across the selected regions. Each
plot represents the peak usage of the cores quota allocated to a region. The image below demonstrates the peak
percentage of cores quota consumed on November 14th, 2020 at 3:32 UTC. The South Central US region, for
example consumed 27% of its quota at that specific date & time. This further detail of regional quota usage is
surfaced in a tooltip when hovering over the plot lines. Users can select the regions plotted on the graph using
the dropdown menu located on the top right corner. By default, the regions with the highest percentage of usage
are selected.

Monitoring peak core usage per build


The quota usage page also tabulates peak core usage for every build within a region. Like the visualization chart
described above, the peak core usage table reports the percentage of peak quota core usage per VM SKU family
per region. This level of detail can enhance the ability to anticipate or diagnose scaling issues quickly, efficiently,
and easily. For example, the image below illustrates core usage across 3 regions: West Europe, South Central US,
and West US. Each table row surfaces the peak core usage and total core quota allocated per region. West
Europe is operating at a higher usage (47%) than South Central US (35%) or West US (28%). Expanding a VM
family using the chevron button next to the family lists the builds of that region/family which includes their peak
usage.
It is important to note that the peak core usage reported in the table is dependent on the time series selected at
the top of the quota summary page. The peak core usage metrics reported in the image above can change if the
time series selection is changed. For example, while West Europe may experience the highest peak core usage
within the last hour, it may experience lower peak core usage than East US or West US if the time series selection
is changed to the last 7 days or last 30 days.
Interpreting Peak core usage readings
The peak core usage reported at the VM family level is the sum of peak core usage of game server builds within
that VM family at a given point in time. In the image above, Dv2 in West US has a peak usage of 1,129 cores.
This is the highest number of cores utilized at one time for Dv2/West US across builds within the selected time
period.

Exporting peak core usage


The peak core usage table supports the ability to export a CSV containing peak usage per build per region. The
two export options are:
Summary CSV
Detail CSV
CSV exports serve as a human readable file of peak core quota usage that can aid capacity planning, on-demand
forecasting or troubleshooting scaling issues specific to a build, region or both.
Summar y CSV
The summary CSV contains the exact data that produces the peak core usage table. Table below shows the
schema used in the CSV:

C SV F IEL DS DESC RIP T IO N EXA M P L E

Region Geo location of build deployment West Europe, East US

Virtual machine family VM SKU family Dv2, Fsv2

Build ID GUID of build asset 0850a980-b45a-40d5-96a9-


8bd1a7dfaa23

Build Name Friendly name of build asset General-Availability-Dec2020


C SV F IEL DS DESC RIP T IO N EXA M P L E

Peak core usage Core quota peak utilized 400

Quota in use Percentage of peak core usage to total 0.25


quota

Total quota Core quota allocated to region/family 45,000 Dv2 cores


pair

Detail CSV
The detail CSV contains the data that also produces the peak core usage table but with additional data sampled
at 1 minute intervals. Therefore a detailed export of a peak core usage table filtered for the last hour containing
a single build deployed in 1 region will produce approximately 60 rows (i.e. 1 build & region row per minute).
The schema of the CSV are:

C SV F IEL DS DESC RIP T IO N EXA M P L E

Region Geo location of build deployment West Europe, East US

Virtual machine family VM SKU family Dv2, Fsv2

Build ID GUID of build asset 0850a980-b45a-40d5-96a9-


8bd1a7dfaa23

Build Name Friendly name of build asset General-Availability-Dec2020

Core usage Core quota utilized at that time 400

Quota in use Percentage of core usage to total 0.25


quota

Timestamp GMT timestamp of core reading Fri Nov 20 2020 05:23:32 GMT+0000

NOTE : Like the core usage table, export data is also dependent on the time series selected at the top of the
quota summary page.

Detecting core quota problems


The Quota Summary page is a powerful resource to help detect core quota problems that impact a game
server’s ability to scale. The following tips can be exercised to mitigate scaling problems in advance.
Status indicators
The build usage table exposes a status indicator adjacent to the region name and the builds within the region.
The indicators include:
Healthy: Usage is 80% below quota limits
Deleted: The build was deleted after its usage was recorded
Warning: Usage is above 80% quota limits
Error: Usage is at 100% or exceeding quota limits
If core usage is approaching quota limits, additional quota can be independently achieved by submitting a quota
change request. Follow the steps in the cores quota change page for next steps.
Tracking title consumption of multiplayer servers
5/24/2022 • 2 minutes to read • Edit Online

In the Multiplayer section of the Game Manager, there is an "Analytics" page on the Servers tab that you can use
to track server consumption. For multiplayer-focused games, server spend can be significant and these tools
help you monitor your estimated bill.
The time-series data available to you via this monitoring experience is a graph showing compute-hours (y-axis)
over time (x-axis). You can adjust the time range.
Multiplayer Servers samples and resources
5/24/2022 • 2 minutes to read • Edit Online

This topic lists samples and resources for PlayFab Multiplayer Game Servers.

Samples
Main repo for all the samples
Wrapper (Windows and Linux)—Using the sample
MpsAllocator—Learn to call frequently used APIs
Windows Runner C#—Using the sample
OpenArena (Linux)
Matchmaking with Server (Using a C# game title)
UnityMirror—Use Unity game engine with PlayFab Multiplayer Servers

Resources
PlayFabMultiplayerAPI module
PlayFab LocalMultiplayerAgent

See also
SDKs overview
Wrapper sample
5/24/2022 • 6 minutes to read • Edit Online

The Wrapper sample, also known as wrappingGsdk, wraps an existing game so it can be used in the deployment
of builds for game servers that use Windows OS and Linux OS .
Using the wrapper application, you would also be able to use your game server build on PlayFab Multiplayer
Servers.

IMPORTANT
A wrapper is a workaround by processing the standard output and error streams to call GSDK methods and it's not
meant for production use.

Sample content
This sample consists of two .NET Core console applications.
Wrapper—integrates the latest Nuget package for the PlayFab Game Server SDK (GSDK) with your game
server. Note that this wrapper application is not meant for production usage
Fakegame—a basic game server that has no knowledge of GSDK. It is like a typical game server that you
would have prior to using PlayFab Multiplayer Servers. It starts the ASP.NET Core Web Server Kestrel that
listens to TCP port 80. It's meant to simulate a game server that has absolutely zero knowledge of GSDK. You
can use it if you don't have a game server of your own. It has two GET routes we can use, /hello for getting a
simple response and /hello/terminate that can terminate the server.

Requirements
.NET Core 3.1 x64 SDK

NOTE
In order to use and view the PlayFab Multiplayer Servers, you need to enable the feature from Game Manager. For
instructions, see Enable the PlayFab Server feature.

Wrapper with Fakegame


If you don't have a game server portion for your game, you can use Fakegame.
1. Get the GSDK wrapper sample using standard Git methods or downloading this as a zip file
2. Build Wrapper executable
3. This step is different depending on the types of servers you want to deploy.
To deploy Windows game servers, see Combine Fakegame and the above Wrapper appplication as a
zip file.
To deploy Linux game servers, see Create and upload Linux container image
4. Deploy a build using Game Manager or API to start creating game servers
For a live walkthrough of building this sample, check out our presentation from Microsoft Game Dev 2021
(starts at about 2.52):
Wrapper with your existing game server build
1. Get the GSDK wrapper sample using standard Git methods or downloading this as a zip file
2. Build Wrapper executable
3. This step is different depending on the types of servers you want to deploy.
To deploy Windows game servers, see Add your game server files and combine them with the
Wrapper application into a zip file
To deploy Linux game servers, see Create and upload Linux container image
4. Deploy a build using Game Manager or API to start creating game servers

Detailed steps
Build Wrapper executable
Open Command Prompt
Use the cd command to change directory path to the wrapper.csproj file location. Example: cd
C:/ReplaceWithYourFilePath/wrappingGsdk/wrapper
Then run the following .NET Core CLI command:

dotnet publish --self-contained -r win-x64 /p:PublishSingleFile=true /p:PublishTrimmed=true

When the wrapper build is successful, the executable is published in the


..\wrappingGsdk\wrapper\bin\Debug\netcoreapp3.1\win-x64\publish folder, as shown in the image below.

Combine Fakegame and Wrapper application


Use the build.ps1 to build and package both projects (wrapper and fakegame). This script will create a drop
folder with a .zip file containing the required files.
Open PowerShell
Use the cd command to change directory path to the build.ps1 script location. Example: cd
C:/ReplaceWithYourFilePath/wrappingGsdk/
Run \build.ps1
After the script runs successfully, go to ..\wrappingGsdk\drop\ folder. You will find a gameassets.zip file
containing the fake game server build, wrapper executable (built in the earlier step), and other required files
is created.
Add your game server files and combine them with the wrapper
To use your game project in the evaluation, place the wrapper and your game server executable in the same
folder.
Follow the instructions at Build the wrapper executable
Go to the wrapper publish location at ..\wrappingGsdk\wrapper\bin\Debug\netcoreapp3.1\win-x64\publish
In another window, go to your game server build and files needed to run your game server build. If you're
unsure what files are needed, see Determining DLL files needed
Copy the gamer server build and all required files into the wrapper publish location
Select all the files in the wrapper publish location
With all the files selected, right-click and then select Send to > Compressed (zip) files to zip . Do not
select the wrapper publish folder and add to zip. This would cause incorrect mapping.

TIP
To cross-check, follow the instructions at Use fakegame project to build the gameassets.zip and use it as a reference.

Create and upload Linux container image


To create a Linux container image, you would need a Dockerfile. A Dockerfile is a text file with no extension and
contains all commands needed to build a given container image. In this sample, this file is already created for
you. All you have to do is to build the container image and run it.
If you wish to use your Windows development device, you would need to install Windows Subsystem for Linux
(WSL). Instructions are provided below. For more information, see Windows and Linux container image
differences.
1. Set up your Windows development device (optional)
2. Get your PlayFab container registry login credentials
3. Use existing/create your own Dockerfile This step is different depending if you are using FakeGame or your
own game server.
If you're using FakeGame, check that you have the Dockerfile
If you're using your game or need to create a Dockerfile, see Create your Dockerfile. You can use the
Dockerfile for FakeGame as a starting point.
4. Open your Linux terminal with Docker installed, like Ubuntu. Replace the values for the TAG and the ACR
variables with your values. Then run the commands below.

TAG="0.1"
ACR="customer5555555.azurecr.io"
docker login ${ACR}

TIP
To check that ACR and TAG variables are properly defined, run echo $ACR and echo $TAG .

5. Enter your username and password obtained from the earlier step.
6. Build and upload the Linux container image.
Run the commands below to build and upload the Dockerfile. Note that there is a "." at the end of docker build
command. You have to be in the same folder/directory as the Dockerfile. For details, see Build and upload Linux
container image.

docker build -t ${ACR}/wrapper:${TAG} .


docker push ${ACR}/wrapper:${TAG}

Deploy a build using Game Manager or API


The deploy build process is quite similar for both Windows and Linux game servers.
Deploy Windows game servers
The steps are similar to the Windows Runner C# sample. Follow these steps with differences listed below.
Use Game Manager to deploy and configure servers
Use PowerShell/API to deploy and configure servers
If you prefer test this locally, see Locally debugging game servers and integration with PlayFab.
Settings specific to this sample
Start command:
Use C:\Assets\wrapper.exe -g C:\Assets\fakegame.exe arg1 arg2
Replace fakegame.exe with the name of your game server executable, if you're using your game
server build
Network configuration: Use port 80 , TCP
Assets: When using FakeGame, upload gameassets.zip as an asset.
Deploy Linux game servers
Follow the general steps below to deploy.
Use Game Manager to deploy and configure servers
Use PowerShell/API to deploy and configure servers
Settings specific to this sample
Select the container you just uploaded
Network configuration: Use port 80 , TCP
No need to upload assets and set Star t Command

NOTE
During the allocation when using RequestMultiplayerServer API, the port you connect to will be different than 80. This is
because the PlayFab Multiplayer Server service will create a mapping between the Azure Load Balancer (that exposes your
ports to the Public internet) to the game servers running on the Azure Virtual Machines.

Running the wrapper using the LocalMultiplayerAgent


Using LocalMultiplayerAgent is highly recommended if you want to test GSDK integration on your custom game
servers.
If you are using LocalMultiplayerAgent with Windows Containers you need to properly configure
MultiplayerSettings.json file. You can find an example below, pay special attention to the values of LocalFilePath
and StartGameCommand. Don't forget to replace fakegame.exe with the name of your game server executable.
"AssetDetails": [
{
"MountPath": "C:\\Assets",
"SasTokens": null,
"LocalFilePath": "C:\\projects\\gsdkSamples\\wrappingGsdk\\drop\\gameassets.zip"
}
],
"StartGameCommand": "C:\\Assets\\wrapper.exe -g C:\\Assets\\fakegame.exe",

// if you are using fakegameserver you should also configure port mapping for port 80
"PortMappingsList": [
[
{
"NodePort": 56100,
"GamePort": {
"Name": "game_port",
"Number": 80,
"Protocol": "TCP"
}
}
]
]

You are now ready to test with LocalMultiplayerAgent. If you have configured it correctly, as soon as
LocalMultiplayerAgent launches your game server, you can connect to it via curl at
http://localhost:56100/Hello .

See also
Create your first server
Resources and samples
PlayFab Multiplayer Server SDKs
API Reference
MpsAllocator sample
5/24/2022 • 2 minutes to read • Edit Online

MpsAllocatorSample can be found here along with the rest of the MPS samples.

This sample is a simple .NET Core application that allows you to easily call some frequently used MPS APIs, like
the ones that list VMs/servers and allocate game servers (RequestMultiplayerServer). To easily and quickly
request a multiplayer server from Game Manager, select the button located at the top of our servers page that
can help you do that. To learn more check out our Servers overview. In order to use it, you need to have installed
.NET Core 3.1 (download here). You can then use either dotnet build command to build an executable for your
platform or just run dotnet run to run the application.

You can find more information about dotnet build command here

In order to authenticate with PlayFab APIs, the app needs your PlayFab TitleID and a developer secret key. To
create a secret key for your title, visit the Settings/Secret-Keys page on the PlayFab developer portal here:
https://developer.playfab.com/en-US/r/t/<Your_TitleID>/settings/secret-keys. You can provide these keys via
environment variables PF_TITLEID and PF_SECRET , or as command line arguments.

The app uses the PlayFab SDK via the corresponding Nuget package

Once you run the application, you can choose which API to call. Each API will ask you to provide necessary
parameters. Here's the list of the available options:
RequestMultiplayerServer: This option will allocate a game server and return its details (IP, FQDN, Port).
Successful invocation of this API call will result in a game server's transition from "StandingBy" state to
"Active" (more here)
ListBuildSummaries: This option will return summaries about your title's Builds
GetBuild: This option will return details about the specified Build
ListMultiplayerServers: This option will return summaries about game servers in a specified Build
ListVirtualMachineSummaries: This option will return summaries about virtual machines in a specified Build
GetMultiplayerServerDetails: This option will return details about a specified game server

See also
Create your first server
Resources and samples
PlayFab Multiplayer Server SDKs
API Reference
Windows Runner C# sample
5/24/2022 • 3 minutes to read • Edit Online

This tutorial lists the steps to get the sample set up ready for use with the PlayFab Multiplayer Servers.

NOTE
In order to use and view the PlayFab Multiplayer Servers, you need to enable the feature from Game Manager. For
instructions, see Enable the PlayFab Server feature.

1. Configure API feature option


2. Create a PlayFab Multiplayer Game Server Build: Server set up
3. Create servers by deploying a build
4. Request multiplayer servers: Client set up. This is needed so you can start a client that connects to the servers

Configure API feature option


NOTE
This step is needed only for running this sample. You do not need to allow clients to start games unless your title requires
this set up.

Log into your developer account on PlayFab.com to use the Game Manager portal
Select your game title
Select the settings icon > API features as shown in the image below.

Under Options , select Allow client to star t games as shown in the image below.
Server set up
Describes how to get the PlayFab Multiplayer Game Server Build.
Download the compiled version of the PlayFab Multiplayer Server Build for the Windows Runner sample.
If you prefer to build this on your own:
Get the Windows Runner C# sample using standard Git methods or downloading this as a zip file.
Open the project using Visual Studio 2017 or later. This should automatically trigger dependencies like
the latest PlayFab Game Server SDK (GSDK) nuget package to be downloaded.
Compile and build the WindowsRunnerCSharp.csproj in release x64 configuration. You would get a
game server build that is integrated with the GSDK, making this a valid PlayFab Multiplayer Game
Server Build.
Go to the bin folder and zip up all the x64 release binaries. There should be no internal folder
structure, the zip file should be a simple flat collection of files, as shown in the image below.

TIP
To cross-check, you can compare your build output with the compiled version provided in the link above.

When you have the zip file, you are ready to start deploying a build.

Create servers by deploying a build


You can deploy a build using one of the following methods.
Use Game Manager to deploy and configure servers
Use PowerShell to deploy and configure servers
For some settings, it may be easier to configure using the web interface—Game Manager.
Next, set up and run the client to connect to the deployed servers.

Client set up
Describes how to get the Windows Runner client application to connect to the game servers you've created
using PlayFab Multiplayer Servers. This can only be set up after you have servers in standby.
After deploying a build, wait for standby servers to be available
Get the titleId and buildId of the build
Using Game Manager:
Go to My Studios and Titles page and look for your game title. Copy the ID value listed there
and paste it somewhere convenient that you can access later. This is the titleId
Select the game title to view the dashboard
Go to Multiplayer > Ser vers > Builds
Copy the ID for the build you want to use and paste it somewhere convenient. This is the
buildId
Using PowerShell, this information is in the output after the build is deployed successfully.
Copy the titleId and buildId and paste it somewhere convenient
Get the Windows Runner C# sample using standard Git methods or downloading this as a zip file. Skip if
you have done this earlier.
Open the project using Visual Studio 2017 or later. This should automatically trigger dependencies like
the latest Game Server SDK nuget package to be downloaded.
Compile and build the WindowsRunnerCSharpClient.csproj in release x64 configuration
Open Command Prompt and navigate to the output folder of this project
Run the WindowsRunnerCSharpClient using this command line, replacing <TitleId> and <BuildID> with
the values above: dotnet WindowsRunnerCSharpClient.dll --titleId <TitleId> --buildId
<BuildId>
Example:

cd
C:\Users\UserName\Documents\GitHub\MpsSamples\WindowsRunnerCSharp\WindowsRunnerCSharpClient\bin\Release\netc
oreapp3.1

dotnet WindowsRunnerCSharpClient.dll --titleId CBE66 --buildId 36083326-3bd5-4b8f-a97d-7e82f066aa40 --


verbose

When the client successfully connects to the server, the Command Prompt would display a log message
informing you that a server is allocated with an IP address.

See also
Create your first server
Resources and samples
PlayFab Multiplayer Server SDKs
API Reference
Walkthrough: Deploy builds using Game Manager
5/24/2022 • 2 minutes to read • Edit Online

This topic describes how to deploy builds for VMs using Windows OS in Game Manager based on the Windows
Runner C# sample.

NOTE
In order to use and view the PlayFab Multiplayer Servers, you need to enable the feature from Game Manager. For
instructions, see Enable the PlayFab Server feature.

Deploying a build is one of the processes in creating a game server using the Windows Runner C# sample.

Prerequisites
Make sure you have completed the following steps.
Configure API feature option
Server set up.

Steps
1. Log into your developer account on PlayFab.com
2. Go to My Studios and Titles page and select your game title to display the dashboard
3. Go to Multiplayer > Ser vers page, select New Build at the top right to create a new build
4. Use "My build" as the Build Name
5. Select a server with limited free usage, such as Av2 (until July 2021) and Dasv4 (from July 2021)
6. Set 1 for Servers per machine
Image below shows values used in the info section section.
7. Under Virtual Machine OS, select Windows as the platform, Windows Ser ver Core as the Container
image
Image below shows values used in the OS section.

8. Under Assets, select Upload then navigate to folder with the compiled PlayFab Multiplayer Server Build for
the WindowsRunnerSample. To get the Build, see Server side set up
Set C:\Assets as the mount path
Image below shows values used in the assets section.
9. Set C:\Assets\WindowsRunnerCSharp.exe as the Start Command.
10. For network, use port 3600 using game_por t as the name. Use TCP as the protocol as shown in the
image below.

11. Under Regions, select "East US", 1 standby server and 1 maximum server.
12. Select Save to start the deployment process. You will be taken to the build home page. The build will
display the Deploying status as show in the image below. In 10 to 20 minutes, your build should be in
the Deployed state.

After servers are deployed, set up the client and connect to the servers.
See also
Walkthrough: Deploying builds using PowerShell/API
Windows Runner C# sample
Samples and resources
Walkthrough: Deploy builds using PowerShell/API
5/24/2022 • 2 minutes to read • Edit Online

This topic describes how to deploy/create builds for Windows OS VMs in PowerShell on a Windows 10
development device based on the Windows Runner C# sample.

NOTE
In order to use and view the PlayFab Multiplayer Servers, you need to enable the feature. We recommend that you use
the Game Manager method to enable this feature. For instructions, see Enable the PlayFab Server feature.

Prerequisites
Make sure you have completed the following steps.
Configure API feature option
Server set up.

1. Get your title ID and developer secret key


Get your PlayFab title ID
Log into your developer account on PlayFab.com
In Game Manager, go to My Studios and Titles page. Look for your game title and get the PlayFab
game title ID
Get the developer secret key for the title
In Game Manager, select your title > settings (gear icon)
Select Title settings , then select the Secret Keys tab to get the developer secret key
For more information about secret keys, see Secret key management

2. Install the PlayFab Multiplayer PowerShell module


Open Windows Powershell as an Administrator and run the following command to install the
PlayFabMultiplayer API module. This new PlayFabMultiplayer API module replaces the deprecated Multiplayer
PowerShell module.
If you have previously installed PlayFab Multiplayer Powershell module, uninstall it with following command.
For those transitioning to the new module, see Mapping commands to find the new equivalent commands.

Uninstall-Package PlayFabMultiplayer

Both the commands and arguments are different in this new module. For detailed documentation about each
command, see Cmdlet documentation.

Install-Module -Name PlayFabMultiplayerApi


TIP
Before installing the module, you may need to set your execution policy using
Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope CurrentUser first. To learn more, see PowerShell
execution policies.

3. Obtain an EntityToken for your title


In the PowerShell window, run the following command using your title ID and associated developer key:

Set-PfTitle -TitleID "mytitleID" -SecretKey "mysecretkey"

4. Upload assets
When you deploy Windows servers, you would use the managed Windows Container. All you have to do is to
upload the PlayFab Multiplayer Game Server Build as an asset.
Update the value of the FilePath flag with the local file location of winrunnerSample.zip . If you don't know
where this file is, follow the instructions here to get the file.

New-PfAsset -FilePath C:\windowsRunnerCSharp.zip -AssetName windowsRunnerCSharp.zip

5. Create a build
Now that the asset is uploaded, we can create a build. Run the following commands.
The code below uses the Standard_D2as_v4 VM in the EastUS region. Replace strings according to the VM
and region you want to use.

$vmSize = "Standard_D2as_v4"

$regions = @( @{ StandbyServers = 1; MaxServers = 1; Region = 'EastUS'; ScheduledStandbySettings = $NULL } )

$ports = @( @{ Name = 'game_port'; Num = 3600; Protocol = 'TCP' } )

$gameAssets = @( @{ FileName = 'windowsRunnerCSharp.zip'; MountPath = 'C:\Assets' } )

$buildResponse = New-PfBuild -BuildName PSTest_build -ContainerFlavor ManagedWindowsServerCore -


StartMultiplayerServerCommand 'C:\Assets\WindowsRunnerCSharp.exe' -GameAssetReferences $gameAssets -VMSize
$vmSize -MultiplayerServerCountPerVM 1 -Ports $ports -RegionConfigurations $regions

# All PlayFabMultiplayerApi cmdlets return objects, so we can pass the returned object to ConvertTo-Json for
human readability.
$buildResponse | ConvertTo-Json -depth 5

Check that your build is successful


In a few seconds, you would see the build created through the PowerShell or ListBuildSummaries API.
You can also run the following command to check that the build deployed successfully.

Get-PfBuild | ConvertTo-Json -depth 5


See also
Walkthrough: Deploy builds using Game Manager
Windows Runner C# sample
Samples and resources
Azure Playfab Multiplayer Game Server SDKs
5/24/2022 • 2 minutes to read • Edit Online

This topic lists the different flavors of Azure PlayFab Multiplayer Game Server SDKs (GSDKs) we have today.

Download links
Note that these SDKs are for the servers.
Game Server SDK GitHub repo for all libraries
Unity Game Server SDK (GSDK)
C++ Game Server SDK (GSDK) for Windows servers via NuGet
C# Game Server SDK (GSDK) for Windows servers via NuGet
Java Game Server SDK (GSDK) for Windows and Linux servers via Maven

TIP
Unsure if this is the SDK you need? See SDKs overview - PlayFab SDK, Party SDK, Multiplayer Game Server SDK.

See also
SDKs overview
How to use PlayFab GSDK Unreal plugin
5/24/2022 • 3 minutes to read • Edit Online

This article describes how to integrate PlayFab Multiplayer Server SDK (GSDK) Unreal Online Subsystem (OSS)
plugin with your Unreal project.
This plugin offers both a Blueprint API and a C++ API. The Blueprint API still requires your Unreal Project to be a
C++ project, and will not work on a Blueprint only project. If it is currently a Blueprint only project, then you
need to convert to a C++ project beforehand, before adding the plugin.
It has been originally tested with Unreal Engine 4.26, 4.27, 5.0 early access, and 5.0 official release . This plugin
will be actively maintained to work with the latest 3 - 4 versions of Unreal. If something fails using these
versions, please open an issue here: Unreal Engine GSDK Repo.
To use these guides, replace all instances of ThirdPersonMP with your project name, if different.

Requirements
Download Visual Studio. The community version is free.
Required workloads: .NET desktop development and Desktop development with C++
Download Unreal Engine Source Code. For instructions, see Downloading Unreal Engine Source code
(external).
If you haven't already, perform a git clone this repo to your local machine
git clone https://github.com/PlayFab/gsdk.git
Later steps will involve integrating files from this repo to your project
[Optional] Download the LocalMultiplayerAgent
[Optional] Alternatively, download LocalMultiplayerAgent source.
[Optional] PlayFab Marketplace plugin or the source version on GitHub. This plugin is not required for GSDK
but is required for many PlayFab services, including login.

Project creation
The Unreal server project needs to be a network-enabled multiplayer Unreal project with a dedicated-server
mode. If you don't have a project that meets these prerequisites, follow our Unreal prerequisite set up guide to
set one up. Once you have a network-enabled, multiplayer project, with a dedicated server, return to this step
and continue.
When ready, open your network-enabled multiplayer Unreal server project, and continue to the next step to
install the Unreal GSDK.

Project GSDK setup


GSDK Project Prerequisite details
Dedicated Server:
Your project should have a separate {ProjectName}Server.Target.cs file
This file should contain Type = TargetType.Server; to enable dedicated server mode
When built in "development server" configuration for Win64, your output contains
{ProjectName}Server.exe
Network-enabled:
There are multiple ways to meet this requirement, but the simple answer is: your client can
establish a network connection with a game-server on a separate machine, and communicate
meaningfully
Our instructions direct you through Unreal's built-in data replication system, which handles
most of this requirement for you
You can establish this connection more directly with a socket, such as through the
ISocketSubsystem, which is a much more advanced topic
Multiplayer:
Your game-server can accept multiple incoming client connections, and communicate properly
with both
Again, with Unreal's built-in data replication, this requirement is mostly handled for you
With a properly configured multiplayer project, you're ready to install the GSDK. This plugin will allow your
server to run on PlayFab Multiplayer Services.

Unreal project build configurations


Once the GSDK is installed and configured in your project, you can build your Unreal project. There are multiple
build configurations you will need to execute the full range of tests in future steps.

Test local server deployment


Once you have any client build, and a "Development Server" build, you can test the MPS deployment process
locally, and verify your server works.

Deploy to PlayFab
You're now ready to create game-servers in the cloud using PlayFab Multiplayer Services. PlayFab MPS supports
Windows servers and Linux servers.

Connect to deployed server


Finally, you're ready to connect to your deployed server.

Acknowledgments
Thank you to Stefan Krismann for creating and submitting this plugin.
Thank you to Nick Arthur for his amazing Dockerfile.
Thank you to Adam Rehn for all his work with Unreal and Docker, including code, samples, examples, and
tutorials.
Example Project Setup
5/24/2022 • 2 minutes to read • Edit Online

This guide covers the construction of an example project which can operate as a game-client and dedicated
game-server. This will set up the minimum requirements for an Unreal project, before the GSDK can be
integrated.
This guide is an excellent starting point if you are starting from scratch.

Goals
The project needs to have the following capabilities and features:
Networking
Multiplayer
Dedicated Game-Server
To accomplish this, we will construct a project from scratch using Unreal tutorials.

Requirements
Download Visual Studio. The community version is free.
Required workloads: .NET desktop development and Desktop development with C++
Download Unreal Engine Source Code. For instructions, see Downloading Unreal Engine Source code
(external).

Instructions
All of the necessary instructions are in the Unreal Tutorials. First, download Unreal Engine Source Build by
following these instructions from the Unreal Engine website.
Next, you should follow the Unreal Third Person Template tutorial. This covers the creation of a basic project we
will use for the rest of this document.
Then, you should proceed to the Unreal Multiplayer Programming Quick Start tutorial. Note, the first step of this
tutorial is an abbreviated version of the one above. This guide upgrades the ThirdPersonMP template to a
multiplayer project.
Once finished with the above guides, you will have a working multiplayer game-client. Next, you need a
dedicated server. At this point, you should proceed to the Unreal Setting Up Dedicated Servers tutorial. This will
set up a dedicated server for your project, and concludes our list of requirements.
Once finished with all guides, you will have a network-enabled multiplayer project with a dedicated game-
server.

Next steps
You are now ready to install the PlayFab Unreal GSDK into this project.
Alternately, you can return to the main Unreal GSDK Plugin guide.
Add GSDK to Project
5/24/2022 • 8 minutes to read • Edit Online

This article describes how to upgrade an existing project so it can be hosted on PlayFab Multiplayer Servers
(MPS). The process involves adding and configuring PlayFab GSDK into an Unreal project. The instructions here
are written using the Unreal ThirdPersonMP template project.
Note, your Unreal project must have the following capabilities:
Networking
Multiplayer
Dedicated Game-Server
If not, you will need to return to the Example Project Setup guide to configure your project as a network-enabled
multiplayer game, with dedicated server capabilities.

Goals
We will add and configure the PlayFab Unreal GSDK to your project, and test it locally to verify it is expected to
work on PlayFab Multiplayer Services.

Requirements
Download Visual Studio. The community version is free.
Required workloads: .NET desktop development and Desktop development with C++
Download Unreal Engine Source Code. For instructions, see Downloading Unreal Engine Source code
(external).
A completed ThirdPersonMP Example Project, or a project with similar capabilities
PlayFab Unreal GSDK plugin
[Optional] PlayFab Marketplace plugin or the source version on GitHub. This plugin is not required for GSDK
but is required for many PlayFab services, including login.

C++ Implementation
Add the plugin to the project
Follow these steps to add the Unreal GSDK to your project:
Go to your Unreal project
Open File Explorer and create a Plugins folder in your games' root directory. In the Plugins folder, create a
folder called PlayFabGSDK.
Go to {depot}\GSDK\gsdk\UnrealPlugin . Drag all the files from the UnrealPlugin folder into the
Plugins/PlayFabGSDK folder.
Lastly, open the {ProjectName}.uproject file in a text editor of your choice. In the plugins array, add the
"PlayFabGSDK" plugin.
See the example below:
{
"FileVersion": 3,
"EngineAssociation": "{YourEngineVersion}",
"Category": "",
"Description": "",
"Modules": [
{
"Name": "{ProjectName}",
"Type": "Runtime",
"LoadingPhase": "Default",
"AdditionalDependencies": [
"Engine"
]
}
],
"Plugins": [ // Add this if it doesn't exist
{ // Add this
"Name": "PlayFabGSDK", // Add this
"Enabled": true // Add this
} // Add this
] // Add this if it doesn't exist
}

Include the plugin in your modules


Update {ProjectName}.Build.cs file to add "PlayFabGSDK" into the
PublicDependencyModuleNames.AddRange(); list as follows:

PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore",


"HeadMountedDisplay", "PlayFabGSDK" });

Right-click on the {ProjectName}.uproject file and select the option to Switch Unreal Engine version ,
which is how you can quickly check which Unreal Engine version you are currently using. The popup seen
below should appear. If you already see that the Unreal Engine version is source build, you don’t need to
change anything, so click Cancel. If the Unreal version is not currently the source build, select it from the
dropdown list and then click OK.

Right-click on the {ProjectName}.uproject file again and select "Generate Visual Studio Project Files".
Finally, build the project in Visual Studio and start the Editor by selecting the Development Editor
configuration.
Project set up
Once your project has enabled server mode, you will have a {ProjectName}Server.Target.cs file.
Result should look similar to:

public class {ProjectName}ServerTarget : TargetRules


{
public {ProjectName}ServerTarget( TargetInfo Target) : base(Target)
{
Type = TargetType.Server;
DefaultBuildSettings = BuildSettingsVersion.V2;
ExtraModuleNames.AddRange( new string[] { "{ProjectName}" } );

// You may have additional configuration based on your server needs


}
}

For Windows builds, you may need to add these optional configurations:

DisablePlugins.Add("WMFMediaPlayer");
DisablePlugins.Add("AsyncLoadingScreen"); //if you are using this plugin
DisablePlugins.Add("WindowsMoviePlayer");
DisablePlugins.Add("MediaFoundationMediaPlayer");

NOTE: These configurations are invalid for a Linux server build.


Create/Update the GameInstance Class
Create a GameInstance Class
If you are in the process of creating a project from scratch and do not yet have a GameInstance class, then first
follow these example instructions to create a GameInstance class. If you are using a project, which already has a
GameInstance class (for example, ShooterGame from Unreal's sample library), then move on to the section titled
Modify the GameInstance class .

In the Unreal Editor:


Select Files
Select Create a new C++ class
Select Show all classes
Type GameInstance into the search field
By selecting it directly as described, everything should be generated correctly and then you can add
the functions we detail below
Close Unreal and Generate project files in source build mode again
Using Visual Studio, open those newly created files and follow instructions to modify the GameInstance class.
Modify the GameInstance class
Locate your GameInstance class, which is most likely called something similar to {ProjectName}GameInstance or
MyGameInstance. From now on, your GameInstance class will be denoted with [YourGameInstanceClassName].
M o d i fy t h e G a m e I n st a n c e h e a d e r fi l e

First, check the include statements and ensure that the following are included in the header file for your
GameInstance class ([YourGameInstanceClassName].h):

#include "CoreMinimal.h"
#include "Engine/GameInstance.h"
#include "MyGameInstance.generated.h"

[Optional] With the following code, the user can introduce a log channel specifically for the GameInstance.
Alternatively, logging with LogTemp is sufficient.

DECLARE_LOG_CATEGORY_EXTERN(LogPlayFabGSDKGameInstance, Log, All);

Then, add the following declarations to the public section: (If you already have an Init() function, there is no need
to include another declaration)

public:

virtual void Init() override;


virtual void OnStart() override;

Then, add the following declarations to the protected section of methods:

protected:

UFUNCTION()
void OnGSDKShutdown();

UFUNCTION()
bool OnGSDKHealthCheck();

UFUNCTION()
void OnGSDKServerActive();

UFUNCTION()
void OnGSDKReadyForPlayers();

};

M o d i fy t h e G a m e I n st a n c e C P P fi l e

Then, locate the [YourGameInstanceClassName].cpp file.


Make sure that the following are included:

#include "[YourGameInstanceClassName].h"
#include "PlayfabGSDK.h"
#include "GSDKUtils.h"

If the custom log channel has been introduced in the header file, then the following code is necessary:
DEFINE_LOG_CATEGORY(LogPlayFabGSDKGameInstance);

Then locate your Init() function. If you don't have an Init() function yet, then add in the function as such:
C re a t e I n i t ( ) f u n c t i o n

void U[YourGameInstanceClassName]::Init()
{
FOnGSDKShutdown_Dyn OnGSDKShutdown;
OnGSDKShutdown.BindDynamic(this, &UMyGameInstance::OnGSDKShutdown);
FOnGSDKHealthCheck_Dyn OnGSDKHealthCheck;
OnGSDKHealthCheck.BindDynamic(this, &UMyGameInstance::OnGSDKHealthCheck);
FOnGSDKServerActive_Dyn OnGSDKServerActive;
OnGSDKServerActive.BindDynamic(this, &UThirdPersonGameInstance::OnGSDKServerActive);
FOnGSDKReadyForPlayers_Dyn OnGSDKReadyForPlayers;
OnGSDKReadyForPlayers.BindDynamic(this, &UThirdPersonGameInstance::OnGSDKReadyForPlayers);

UGSDKUtils::RegisterGSDKShutdownDelegate(OnGSDKShutdown);
UGSDKUtils::RegisterGSDKHealthCheckDelegate(OnGSDKHealthCheck);
UGSDKUtils::RegisterGSDKServerActiveDelegate(OnGSDKServerActive);
UGSDKUtils::RegisterGSDKReadyForPlayersDelegate(OnGSDKReadyForPlayers);
}

If you already had an Init() function, go to check in [YourGameInstanceClassName].cpp file to see if you have a
variable that indicates whether the instance is for a dedicated server. If you can find this variable , then add
the following to the end of your Init() function:
M o d i fy exi s ti n g I n i t() fu n c ti o n

if (IsDedicatedServerInstance() == true)
{
FOnGSDKShutdown_Dyn OnGsdkShutdown;
OnGsdkShutdown.BindDynamic(this, &UShooterGameInstance::OnGSDKShutdown);
FOnGSDKHealthCheck_Dyn OnGsdkHealthCheck;
OnGsdkHealthCheck.BindDynamic(this, &UShooterGameInstance::OnGSDKHealthCheck);
FOnGSDKServerActive_Dyn OnGSDKServerActive;
OnGSDKServerActive.BindDynamic(this, &UShooterGameInstance::OnGSDKServerActive);
FOnGSDKReadyForPlayers_Dyn OnGSDKReadyForPlayers;
OnGSDKReadyForPlayers.BindDynamic(this, &UShooterGameInstance::OnGSDKReadyForPlayers);

UGSDKUtils::RegisterGSDKShutdownDelegate(OnGsdkShutdown);
UGSDKUtils::RegisterGSDKHealthCheckDelegate(OnGsdkHealthCheck);
UGSDKUtils::RegisterGSDKServerActiveDelegate(OnGSDKServerActive);
UGSDKUtils::RegisterGSDKReadyForPlayers(OnGSDKReadyForPlayers);
}

Complete the Init() function by calling the following function that sets up the default port for MPS.

#if UE_SERVER
UGSDKUtils::SetDefaultServerHostPort();
#endif

Lastly, add these method implementations to the bottom of [YourGameInstanceClassName].cpp file:


void UMyGameInstance::OnStart()
{
UE_LOG(LogPlayFabGSDKGameInstance, Warning, TEXT("Reached onStart!"));
UGSDKUtils::ReadyForPlayers();
}

void UMyGameInstance::OnGSDKShutdown()
{
UE_LOG(LogPlayFabGSDKGameInstance, Warning, TEXT("Shutdown!"));
FPlatformMisc::RequestExit(false);
}

bool UMyGameInstance::OnGSDKHealthCheck()
{
UE_LOG(LogPlayFabGSDKGameInstance, Warning, TEXT("Healthy!"));
return true;
}

void UThirdPersonGameInstance::OnGSDKServerActive()
{
/**
* Server is transitioning to an active state.
* Optional: Add in the implementation any code that is needed for the game server when
* this transition occurs.
*/
UE_LOG(LogPlayFabGSDKGameInstance, Warning, TEXT("Active!"));
}

void UThirdPersonGameInstance::OnGSDKReadyForPlayers()
{
/**
* Server is transitioning to a StandBy state. Game initialization is complete and the game
* is ready to accept players.
* Optional: Add in the implementation any code that is needed for the game server before
* initialization completes.
*/
UE_LOG(LogPlayFabGSDKGameInstance, Warning, TEXT("Finished Initialization - Moving to StandBy!"));
}

Blueprint implementation
This part is only needed if you have decided to proceed with the Blueprint implementation and not with the pure
C++ implementation. Some of the nodes presented below are outdated. We advise users who prefer the
Blueprint implementation to consult the C++ implementation for the nodes that will be required.
Observe the Content Browser window in the Unreal Editor
Pick or create a folder to contain new Blueprints
Right-Click and create a Blueprint class
In the All classes dropdown menu, find your GameInstance class
In this example, the blueprint is named "MyGameInstance"
Double-click the blueprint
On the left side, hover over the function field and select the Override dropdown
Select the Init function
Right-click in the graph and add in all register GSDK function
For GSDK Shutdown and Maintenance Delegate drag out a line from the red square, and select "Add Custom
Event"
For "Register GSDK Health Check Delegate", select the "Create Event" in the "Event Dispatchers".
In the dropdown of the new node "Create matching function". This is impor tant, as the GSDK Health
Check Delegate has a return value.

In the function, make sure the return boolean value is checked.

Don't forget to connect all the nodes to the Event Init node.
Add "Ready for Players" to be able to react to the ready signal of PlayFab.
Set the GameInstance class
After creating a custom GameInstance class that integrates with the gsdk, you have to configure your project to
actually use this newly created GameInstance class. There are two ways to do this - either through the Unreal
Engine editor or by editing DefaultEngine.ini directly.
In the Unreal Editor
In the editor, the default GameInstance can be set through the UI in the editor. In the editor, go to Edit -> Project
Settings . From that opened window, navigate to Maps&Modes on the left side. Scroll to the bottom, and then
you can set the option GameInstanceClass to your new GameInstance class directly (avoid typos, it must be an
exact match).
In DefaultEngine.ini
Or you can update DefaultEngine.ini file and add the following lines:

[/Script/EngineSettings.GameMapsSettings]
GameInstanceClass=/Script/{ProjectName}.MyGameInstance

Include Pre-requisites for Windows Dedicated Server


There are two ways to include the app-local prerequisites - either through the Unreal Engine editor or by editing
DefaultGame.ini.
In the Unreal Editor
In the editor, go to Edit -> Project Settings. In the opened window, navigate to Packaging on the left side. Scroll
to the bottom of the list, and tick "Include app-local prerequisites".
In DefaultGame.ini
Or you can update DefaultGame.ini with the following code:

[/Script/UnrealEd.ProjectPackagingSettings]
IncludeAppLocalPrerequisites=True

If the category already exists in your DefaultGame.ini, then just add the second line to it. This configuration
ensures that all app local dependencies ship with the project as well.
If you are using Continuous Integration (CI), then you could add it to your setup to only turn on this flag when
building a dedicated server, so the prerequisite dlls only get added if it is a dedicated server build.

Next steps
You are now ready to build your project on your local machine.
Alternately, you can return to the main Unreal GSDK Plugin guide.
Build the ThirdPersonMP Example Project
5/24/2022 • 3 minutes to read • Edit Online

This article describes how to successfully build a PlayFab Multiplayer compatible Unreal project using the Unreal
ThirdPersonMP sample as a template project. In this guide you will find all the build configurations needed by
later steps to test and verify your Unreal project. There are no special GSDK steps on this page, this only covers a
specific set of Unreal build instructions useful for this example.

Goals
Build the "Development Editor"
Build a game-client
Build the "Development Server"
Build a release Server

Requirements
Download Visual Studio. The community version is free.
Required workloads: .NET desktop development and Desktop development with C++
Download Unreal Engine Source Code. For instructions, see Downloading Unreal Engine Source code
(external).
Completed Unreal Project with PlayFab Unreal GSDK installed and configured
Knowledge about Unreal Build Configuration options

Instructions
The GSDK setup guide previously described the steps to "Switch Unreal Engine Version" and "Generate Visual
Studio project files". There is also an Unreal guide about the various compilation options, which you should
review.
Development Editor
The development editor should be the first thing you build. To do this, find your {ProjectName}.uproject file,
right-click, and "Generate Visual Studio project files" (You may have already done this in the previous guide, in
which case, you can skip this step. Once complete, you can open {ProjectName}.sln in Visual Studio.
Once Visual Studio loads, change your configuration to "Development Server". The Solution Configuration
dropdown is sometimes hard to read, but can be resized in the toolbar customization options. Now, build. The
first time you do this, it can take several hours, but you likely did this in the previous guide. Repeated builds
should be fairly fast for a small project. Once finished, you can run/debug the project
Solution/Games/ThirdPersonMP. This will start the Development Editor.
Build Shipping Client
Run the Development Editor. From the development editor window, pick these options in this order:
File -> Package Project -> Build Target -> ThirdPersonMP (Or the name of your project)
File -> Package Project -> Build Configuration -> Development
File -> Package Project -> Windows (64-bit)
(This opens a popup window asking you to pick a location - make sure you remember this location)
The first time packaging occurs in this configuration, it may take a while
The first shipping client build will take upto multiple hours, even if you've already built Development
Editor
Repeat builds will be much faster for a simple project like ThirdPersonMP
Open the client location you picked and find ThirdPersonMP.exe
Build Development Server
Close the Development Editor (Unreal is no longer running, only Visual Studio should be open now)
Toolbars -> Configuration -> "Development Server"
Build/Rebuild Solution
The first time packaging occurs in this configuration, it may take a while
The first development server build will take upto multiple hours, even if you've already built
Development Editor
Repeat builds will be much faster for a simple project like ThirdPersonMP
Use Explorer to find {projectLocation}\Binaries\Win64\ThirdPersonMPServer.exe
Build Shipping Server
Run the Development Editor. From the development editor window, pick these options in this order:
File -> Package Project -> Build Target -> ThirdPersonMPServer (Or the name of your project)+Server
File -> Package Project -> Build Configuration -> Development
File -> Package Project -> Windows (64-bit)
(This opens a popup window asking you to pick a location - make sure you remember this location)
The first time packaging occurs in this configuration, it may take a while
The first shipping server build will take upto multiple hours, even if you've already built Development
Editor
Repeat builds will be much faster for a simple project like ThirdPersonMP
Open the server location you picked and find ThirdPersonMPServer.exe

Next steps
You are now ready to deploy your game server on your local machine.
Alternately, you can return to the main Unreal GSDK Plugin guide.
ThirdPersonMP Example Project Local Deployment
and Debugging
5/24/2022 • 6 minutes to read • Edit Online

The purpose of this guide is to demonstrate running your game-server on your local machine, in a MPS-
compliant way, so you can test and debug your server before uploading it to PlayFab.

Goals
Test the local deployment options for the ThirdPersonMP+GSDK project.
Verify your server executes properly when run using LocalMultiplayerAgent
Verify you can attach a debugger to your server instance

Requirements
Download Visual Studio. The community version is free.
Required workloads: .NET desktop development and Desktop development with C++
Download Unreal Engine Source Code. For instructions, see Downloading Unreal Engine Source code
(external).
Completed Unreal Project with PlayFab Unreal GSDK installed and configured
"Development Server" configuration of your project built from Visual Studio
[Optional] Download the LocalMultiplayerAgent
[Optional] Alternatively, download LocalMultiplayerAgent source.
"Debug" or "Release" configuration of LocalMultiplayerAgent built from this repo with Visual Studio
Using Visual Studio, Open MpsAgent.sln, Select either Debug or Release configuration, and then build
the LocalMultiplayerAgent.
[Optional] Install Docker for Windows

Notation
{depot} will refer to the full windows path for the location where you download your Git projects. These can be
anywhere you like, such as: C:\depot, S:\depot, Z:\gitrepos or whichever drive and path are convenient for you. It
is typically recommended (especially for Unreal), that your {depot} path be very short, if possible. For the author,
{depot} resolves to: M:\depot\GSDK . For example, with the requirements list above, you will likely have some or
all of the following:
{depot}/ThirdPersonMP
{depot}/MpsAgent
[Optional] {depot}/gsdk [This contains the PlayFab Unreal GSDK plugin previously installed into
ThirdPersonMP]
[Optional] {depot}/UnrealMarketplacePlugin [This contains the PlayFab Unreal Marketplace plugin, which is
not required for this guide, but almost certainly required for other PlayFab features]
It is not required that you have all of these in the same location, but it is likely useful to do so, and for
organization, this guide encourages you to do so.

Instructions
Local execution, no containers
First, you will need to configure your LocalMultiplayerAgent to execute your server project. The first iteration
will run the process directly on your local PC without any isolation.
In Explorer, find and open the file: {depot}\MpsAgent\LocalMultiplayerAgent\MultiplayerSettings.json . An
abbreviated version of this file with the parts important to this guide are as follows [NOTE the escaped \'s for
paths in the json - this is a json file, and thus it's required to escape all \'s as \\]:

{
"RunContainer": false,
...
"AssetDetails": [
{
"MountPath": "C:\\Assets",
"LocalFilePath": "{PATH-TO-ZIP}"
}
],
...
"PortMappingsList": [
[
{
"NodePort": 30000,
"GamePort": {
"Name": "UnrealServerGsdkHostPort",
"Number": 8888,
"Protocol": "UDP"
}
}
]
],
"ProcessStartParameters": {
"StartGameCommand": "{PATH-TO-EXE} -log"
},
"ContainerStartParameters": {
"StartGameCommand": "C:\\Assets\\ThirdPersonMPServer.exe -log",
...
}
}

For the purposes of this guide, the parts of the json file obscured by ... above, just utilize the project defaults.
The purpose and values for the important fields are as follows:
RunContainer: For this guide, this will always be false. Setting this to true requires Docker.
When true, the ProcessStartParameters/StartGameCommand is ignored, and
ContainerStartParameters/StartGameCommand is used instead
When true, everything is built and run in a docker container, rather than on the local machine context
This guide covers the scenario when RunContainer is false, so that we can more easily debug the
server process
Setting this to true requires a Shipping Server build, additional Windows DLLs or Linux dependencies,
and Docker for Windows
AssetDetails/LocalFilePath: {PATH-TO-ZIP}
This location must be fully defined, and a valid zip file must exist at this location
This zip file should contain a fully constructed "Shipping Server" build
PortMappingsList:
This is the LocalMultiplayerAgent equivalent of defining the port in Game Manager
The GSDK plugin is hard-coded to look for a port with the name: UnrealServerGsdkHostPort
The GSDK plugin SetDefaultServerHostPort method will internally override the internal Unreal server-
hosting port to match this port
The GSDK plugin will only use the port named UnrealSer verGsdkHostPor t , which is configured in
Por tMappingsList when using LocalMultiplayerAgent.
This json lets you locally test driving this port number from MPS, and ensures your GSDK plugin will
receive it properly
ContainerStartParameters/StartGameCommand: While RunContainer is false, this is unused.
When RunContainer==true, it supersedes the ProcessStartParameters/StartGameCommand
This path is the internal path within the docker container, and will be the sum of
AssetDetails/MountPath, plus the internal path-to-exe in your zip file defined by
AssetDetails/LocalFilePath
For this example, this could be: C:\\Assets\\ThirdPersonMPServer.exe -log
ProcessStartParameters/StartGameCommand: This command will effectively be the path to your exe, and any
command-line parameters used to start your game server
-log is an Unreal command to instruct the game-server to save an execution log
{PATH-TO-EXE} can be one of two choices:
Any absolute path to an exe for your game server (even development game server), plus any
command-line parameters for your server
This choice will ignore the contents of the zip file, and instead execute any arbitrary exe
in any location
This is a local debug option that only works on your local machine to debug
development builds: It does not help you verify your zip file is ready to upload to MPS
This choice should be used when testing a development server, suitable for attaching a
VS debugger
For this example, this could be:
{depot}\\ThirdPersonMP\\Binaries\\Win64\\ThirdPersonMPServer.exe -log
For the author, this is:
M:\\depot\\GSDK\\ThirdPersonMPGSDK\\Binaries\\Win64\\ThirdPersonMPServer.exe -log
A relative path, which should indicate the relative path into your zip file, to run your server
This is the standard workflow that mirrors how it works on an MPS cloud instance
This choice should be used when testing a shipping server, and helps verify your zip is
ready to upload to MPS
For this example, this could be: ThirdPersonMPServer.exe -log

Once you have created your zip file and set all of these lines to appropriate values, you can rebuild your
LocalMultiplayerAgent, and prepare to debug your server.
Debug your server
You can run LocalMultiplayerAgent from Visual Studio with the "Start New Instance" command, sometimes
bound to F5, or you can navigate to {depot}\LocalMultiplayerAgent\bin\{configuration}\netcoreapp3.1 and
double-click "LocalMultiplayerAgent.exe". You can also run this from within a cmd window to observe or capture
debug log information.
Running LocalMultiplayerAgent.exe should start your game server. You will usually want to have Task Manager
open for this. You can find your game server process ID in the Details tab of Task Manager.
Once you see your ThirdPersonMPServer process running in Task Manager, you can return to Visual Studio,
select the Debug dropdown -> Attach to Process. From the popup window, you can search your process name:
ThirdPersonMPServer, and then select the proper process ID, identified from Task Manager.
At this point, you should be able to perform typical debugging into your game server.
NOTE: Unreal provides multiple build configurations and multiple ways to build your server. For best results, use
the "Development Server" configuration, and output, built directly from Visual Studio. Shipping builds, or builds
from the Development Editor may work better for other situations, but the "Development Server" configuration
built directly from Visual Studio will be easier to attach and debug in Visual Studio.

Troubleshooting
Many instances of ThirdPersonMPServer in Task Manager
If there are multiple instances listed (usually 3 or more), you may need to use Task Manager to force-close
instances that are lingering from previous attempts.
LocalMultiplayerAgent launches 2 instances of ThirdPersonMPServer
If your LocalMultiplayerAgent starts multiple instances, look for the process ID with a comparatively high
memory use. Some configurations of the game server generate two executables, which run as a pair. You will
want to attach to the one with a much higher memory use.

Next steps
You are now ready to deploy your server to the cloud.
Alternately, you can return to the main Unreal GSDK Plugin guide.
Deploy and Run Windows Server in the Cloud
5/24/2022 • 5 minutes to read • Edit Online

This guide explains how to deploy your Windows server build to PlayFab Multiplayer Server (MPS) cloud. This is
great for testing and rapid iteration of your game server while in development. Many users will use Linux
servers for a production release after testing with Windows.

Goals
Deploy a project to the cloud.
Connect to it from a local game-client

Requirements
Download Visual Studio. The community version is free.
Required workloads: .NET desktop development and Desktop development with C++
Download Unreal Engine Source Code. For instructions, see Downloading Unreal Engine Source code
(external).
Completed Unreal Project with PlayFab Unreal GSDK installed and configured
Release Server configuration of your project built from Visual Studio or Development Editor
Client configuration of your project built from Visual Studio or Development Editor
MPS is enabled for your title, and billing is set up
[Optional] Install Docker for Windows

Instructions
Package the game -server
[OPTIONAL] This section can be done to refresh the files which Unreal builds into your project. This is useful
if you've recently created or deleted files.
If you have not recently built your project in "development editor" configuration, do so now
Close Visual Studio
Navigate to the {ProjectName}.uproject file for your project
Right-click on the {ProjectName}.uproject file in your file editor and select "Generate Visual Studio
Project Files"
Re-open the {ProjectName}.sln file in Visual Studio
Select Development Editor configuration
Run your project
Observe the Unreal Editor, which should have loaded your project
In the top left of the Unreal editor menu, Select File -> Package -> Build Target -> {ProjectName}Ser ver
Select File -> Package -> Build Configuration -> Shipping
Select File -> Package -> Windowsx64
Select and remember an output location {ShippingServerFolder}
You can now use this packaged version of your game-server to test with LocalMultiplayerAgent
Once verified with LocalMultiplayerAgent, see creating a build guide
Testing on MPS at this point will require an intermediate tool from PlayFab MpsAllocatorSample
This tool bypasses some client work for now, and allows us to allocate a server without a direct
request from the game-client
The proper way to do this on a client is a separate topic covered in the allocation guide.
Zip your Shipping Server build from {ShippingServerFolder} above
Your zip should contain everything in {ShippingServerFolder}, optionally at the root of the zip file
[Optional] IE, the root of your zip should contain {ProjectName}Server.exe (It's suggested the exe
should not be in a subfolder such as "WindowsServer". Rebuild your zip if desired)
Get familiar with the build creation process guide
Specific details for specific configurations are detailed below:
Set up a Windows Dedicated Server on PlayFab
This section will cover creating a build in PlayFab MPS, uploading your game-server, and connecting to it for the
first time. You can also follow the core MPS server creation guide for less Unreal specific instructions.
Navigate to Game Manager -> Multiplayer
Select New Build
Give the build a name
Select a Virtual Machine (For the samples described in these guides, the recommended option with the
fewest cores is sufficient)
Servers per machine can be approximately 1~10
Improving/Raising this number is based on the performance of your game-server
You can use VM metrics to measure performance of your game server, and optimize to raise this
number
Skip Ser ver details for now (covered in the next step)
In the Assets block, drag your zip file from the previous section into the upload box
If you're re-launching, you can select Use existing assets
Wait for the upload to complete
Skip Star t Command for now (covered in the next step)
In the Network block, set the Port Name field to UnrealServerGsdkHostPort
It's mandatory to define the port that will be used to connect to your game-server
Unreal GSDK contains code to read this port automatically, and internally override the Unreal Server
host port according to this value
The name of this port is required to be UnrealServerGsdkHostPort
Continue to the next step that matches the "Server Details" that you want to configure
Option 1: Windows Process Mode
This option runs your game-server(s) as a process directly on the VM. Your processes will share access to the full
machine, including ports, drives, etc. This option unzips your asset upload, and executes the "Start Command"
from the location of your unzipped files as the working directory.
In Ser ver Details , select Process and Windows
In Assets , set the start command to:
{ProjectName}Server.exe or {ProjectName}Server.exe -log if you want to generate log files
The start command is executed from the command-line, using your unzipped asset files as the
working directory
If you chose to pack your zip file with sub-folders, you can specify a relative path such as:
WindowsServer/{ProjectName}Server.exe to access your project with a relative sub-path
Select Add Build
Skip ahead to the Configure Regions section below
Option 2: Windows Container Mode
This option runs your game-server(s) in docker containers, isolating them from each other. Each server process
will have a separate virtual drive, virtual network ports, etc. This option unzips your asset to a Mount Path you
will define, and expects your start command to be a full path, based on the Mount Path.
Prerequisite requirement: Configure Docker to run Windows containers
In Ser ver Details , select Process and Windows
In Assets
Set the Mount Path for your gameServer zip file to C:\assets (or something similar, denoted as
{MountPath})
Set the start command to: {MountPath}\{ProjectName}Server.exe or
{MountPath}\{ProjectName}Server.exe -log if you want to generate log files
The start command should represent a full path in the container, to your -Server.exe file
If you chose to pack your zip file with sub-folders, you can specify an absolute path such as:
{MountPath}\WindowsServer\{ProjectName}Server.exe to access your project with an absolute sub-path
Select Add Build
Skip ahead to the Configure Regions section below

Next steps
Many users will want to test their server by connecting a game client.
Other users may optionally continue on to rebuild and redeploy their servers using Linux containers. Linux
reduces the server-hosting costs for large-scale deployment.
Otherwise, you can return to the main Unreal GSDK Plugin guide.
Set up a Linux Dedicated Server on PlayFab
5/24/2022 • 4 minutes to read • Edit Online

The purpose of this guide is to describe all the steps needed to build and verify a Linux dedicated server. The
following steps are specific to Unreal Engine 5 (both early access and official release). The same set of steps have
been tested and apply also to UE 4.26 and UE 4.27, with some minor differences related to the location of the
packaging option on the Unreal Engine UI, which is different in UE 4.27 and UE5 early access.
More Linux deployment information can be found here

Requirements
Install Unreal Linux prerequisites
Install Docker for Windows

Instructions
From Unreal Linux prerequisites , download the toolchain for your installed Unreal Engine and run the
executable. Note, like many parts of these guides, these steps will work only if your Unreal Engine built from
source.
After the installation is complete, examine your Windows environment variables and confirm the
following system variable exists: LINUX_MULTIARCH_ROOT .
In your Unreal Engine source directory:
Rerun: Setup.bat
Rerun: GenerateProjectFiles.bat
Return to your own project:
Right-click your {ProjectName}.uproject file, and Generate Visual Studio project files
Open the {ProjectName}.sln file in Visual Studio
Set the configuration to Development Editor
Build and run the Unreal Editor
At this point, you should be able to package your project for Linux server in a directory of your choice.
For Unreal Engine 5, in the Editor, click packaging on the top right of the screen and the Linux option
should now be available to be selected. For UE 4.26 and UE 4.27, the packaging option lies under the
file tab.
Confirm your configurations for Server & Shipping, select Linux to build, and then select the output
directory.

Create Docker image of the Linux server


In this section, we'll set up a Docker image that contains your Linux Server
Now that you have created a Linux server, navigate to that directory (Windows Explorer, or terminal of your
choice)
Create a new file named: Dockerfile
Edit the file with your editor of choice (notepad, vim, emacs etc.)
Copy - paste the content presented below. Make sure to replace [YourProjectNameServer].sh with the name
of your own linux server executable (in the same directory)
FROM ubuntu:18.04

# Unreal refuses to run as root user, so we must create a user to run as


# Docker uses root by default
RUN useradd --system ue
USER ue

EXPOSE 7777/udp

WORKDIR /server

COPY --chown=ue:ue . /server


USER root
CMD chown -R ue.ue $PF_SERVER_LOG_DIRECTORY && su ue -c ./YourGameNameServer.sh

NOTE: The chown command fixes the $PF_SERVER_LOG_DIRECTORY to be accessible by your server process,
and then && chains the command to execute your server
Using a terminal of your choice, navigate to the Linux server directory
Windows users typically use cmd or powershell, though bash via third party tools or WSL are also
available
Mac and Linux users typically use bash
Run: docker build -t "[imageName]:[tag]" . , where imageName and tag are options of your choice.
Remember these names, you will use them again
Examples could be: YourProjectNameSer ver and 01 respectively
The tag element is typically used to version your server instance
These tags will be used in a later step
You can type docker images on the terminal to retrieve imageName and tag if you forget
Type docker images on the terminal to inspect the successful creation of the docker image.
Keep this terminal window open and set it aside as we will have more commands for it later
(Denoted as [Docker terminal] in later steps)

Upload the container image on the PlayFab Azure registry


At this point, you are ready to push your docker image in the PlayFab Azure Container Registry so that it can be
used to launch your build on PlayFab.
Navigate to the PlayFab developer portal
Select your title
Select the Multiplayer tab on the left
Select New Build on the right of the screen.
Choose a name
Select a VM type, for ThirdPersonMP projects Dasv4 (2 cores) will be sufficient
Under Server Details, set Server Type to Container and Operating System to Linux .
Click the Upload to container registr y button.
On the window that pops up:
Remember your [AzureUsername] from this window, used multiple times in next steps
Select Copy Docker Login Command
Return to the {Docker terminal} window
Paste the Docker Login command into [Docker terminal]. This command will log you into the Azure
Registry used by PlayFab.
type: docker tag [imageName]:[tag] [AzureUsername].azurecr.io/[imageName]:[tag]
Type: docker push [AzureUsername].azurecr.io/[imageName]:[tag]
Recall, AzureUsername was displayed on the PlayFab developer portal, and imageName and tag
where chosen by you earlier.
Back on the PlayFab website, under the Server Details on the New Build page, click Refresh next to Container
image.
Click the arrow button and you should be able to see and select the docker image you uploaded and the
respective tag.
In the Regions block, select a region close to you, and set both Standby and Max to 1 ( just for testing)
In the Network block, set the Port Name field to UnrealServerGsdkHostPort
It's mandatory to define the port that will be used to connect to your game-server
Unreal GSDK contains code to read this port automatically, and internally override the Unreal Server
host port according to this value
The name of this port is required to be UnrealServerGsdkHostPort
Select Add Build , and wait for your build status to become Deployed

Next steps
Many users will want to test their server by connecting a game-client.
Otherwise, you can return to the main Unreal GSDK Plugin guide.
Connect to MPS hosted build
5/24/2022 • 3 minutes to read • Edit Online

This article describes how you can connect clients to PlayFab Multiplayer Servers (MPS) hosted servers using a
utility tool. This tool is used during development to bypass typical steps to provision and activate servers. Earlier
steps in this example sequence covered adding the Unreal GSDK to a standard ThirdPersonMP tutorial project. In
doing so, we set up the server connection side, but we ignored a proper client connection sequence. PlayFab
requires servers to be provisioned and activated before clients can connect to them. We will not cover that
process here, but more details are available in the MPS Documentation. Instead, for this example, we will bypass
those complicated steps and instead use a manual utility to rapidly test connections between the client and
server.

Prerequisites
Clone or download the MpsSamples repo
A fully deployed ThirdPersonMP server in "Deployed" status, with at least 1 server fully propped and in
"Standby" mode
ThirdPersonMP is the sample project built and deployed in earlier pages of this guide.
A build's status becomes "Deployed" when it contains servers that are ready for connections. These
servers are considered in "Standby"
A built game-client, ready to connect
Visual Studio with .Net Core 3.1 (available as an optional checkbox in the Visual Studio Installer)

How to connect a client automatically to the server


Your built game-client will likely be ThirdPersonMP.exe and be located in or near your project. If you did not
use ThirdPersonMP as a starting template, then your built game-client will be {YourProjectName}.exe ,
similarly located in or near your Unreal project. Find this file.
Find ThirdPersonMP.exe
Create a new adjacent file RunCloud.bat
Open this file in a text editor of your choice, and set the following contents:

ThirdPersonMP {IP-ADDRESS}:{PORT} -log

NOTE: Replace ThirdPersonMP with your project name if necessary.


For now, we do not yet know the IP-ADDRESS or PORT, so just save, and leave the editor open.
Find the file {MpsSamples Repo}/MpsAllocatorSample/MpsAllocatorSample.csproj
Open this file in Visual Studio
Run this program
Follow the on-screen instructions, and input the following values when prompted:
{Your PlayFab TitleId}
{Any valid and active secret key for your PlayFab Title}
Choose 1 to RequestMultiplayerSer ver
Enter the {BuildId} for the Deployed -Status server build you wish to test
This can be found next to the name in the list of all builds, in the Details tab of the specific
build, or in the URL for any of the build specific pages
If you have multiple regions defined, you'll be prompted to select one. Otherwise, it will auto-select if
there is only 1 available region.
For Player IDs, you can type real, or fake hex-number value
For users who followed the ThirdPersonMP setup, you can pick any hex-number, such as 1337,
abc123, or etc.
Input at least 1 number, and then hit enter an extra time to finish
You should receive a response that looks like this:

{
"ConnectedPlayers": [],
"FQDN": "...",
"IPV4Address": "52.180.68.101",
"LastStateTransitionTime": "2021-12-06T22:12:46.212Z",
"Ports": [
{
"Name": "UnrealServerGsdkHostPort",
"Num": 30000,
"Protocol": "UDP"
}
],
"Region": "WestUs",
"ServerId": "...",
"SessionId": "...",
"State": "Active",
"VmId": "..."
}

NOTE: Values unimportant to this example have been replaced with ...
Look for IPV4Address and Por ts.Num in your response
In the example above, these values are: 52.180.68.101 and 30000 respectively
Your values can/will be different
Return to your RunCloud.bat file, and fill in these values for IP-ADDRESS and PORT. Example:

ThirdPersonMP 52.180.68.101:30000 -log

From windows explorer, double click this .bat file, to run the game-client, wait a moment, and then double
click it again
This should start two instances of your game-client, both connected to your cloud hosted game server
From here, you can run around in both games, and you should see that both users' movements and actions
are reflected in both game clients, for both players
SUCCESS! If you see that, you've completed the full Setup/Build/Deploy/Connect process

Navigation
For some users, this guide sequence is now finished. You can return to the main Unreal GSDK Plugin guide.
If your test was run on Windows servers, then you can try the more advanced Linux Server deployment guide.
Matchmaking
5/24/2022 • 4 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

Overview
The new PlayFab Matchmaking feature provides a great way to build matchmaking into your game and offers a
simple, yet powerful system to help your users find each other. This feature is an upgrade to PlayFab's existing
matchmaker and uses the proven capabilities of Xbox Live's SmartMatch.
This marks the first time the firmly established technology of Xbox Live matchmaking has been available outside
of the Xbox Live ecosystem, and it will be available to you everywhere via PlayFab.
When an individual or group wants to enter a match, your title submits a request to the matchmaking service.
Once the request is made, the service will hold on to the request and try to match it with other requests. The
service then creates matches that contain players who are most compatible.

Terminology
There are a few common terms used throughout the matchmaking system that we'll need to define. They are:
Ticket - A ticket is the resource at the core of the matchmaking process. A ticket consists of a player or a
list of players that want to play together, along with their attributes (such as in-game levels, favorite
maps, or skill).
Queue - A queue is a collection of tickets to be matched together and a set of rules that controls how
tickets are matched.
Rule - A rule is a constraint on which tickets are eligible to match. The matchmaking algorithm searches
for a set of tickets that satisfy all the rules defined by a queue to create a match.
Attribute - An attribute is a value associated with a player that can have Rules applied to it. Attributes
can be specified in either the ticket or the player's Entity Objects.
Match - A match is the output of the matchmaking process. It is a collection of tickets that satisfy all the
rules for the queue the tickets were submitted to.

Basics
When a player or group of players want to play together, one player creates a ticket for themselves or the entire
group, and submits it to matchmaking through your title. The join flow ensures that all players in the group
consent to match together. Once the player or players have joined, the matchmaking process begins
automatically. When matchmaking finds a suitable match, the title must group those matched players together
into a game.
A ticket is submitted to a matchmaking queue. A title can have multiple queues. For example, a title might create
one queue for a ranked game mode and another for a social game mode. Tickets can only match with other
tickets in the same queue, and a player may only be in one ticket at a time.
To define a queue, you must create a queue configuration. The simplest configuration consists of the queue
name and the match size (a minimum and maximum number of players). The matchmaking service will attempt
to fill the match to the max size provided, but if insufficient tickets are available a match of the minimum size
can be generated.
If you have different game modes with different match size requirements, it is best to create multiple queue
configurations. For more advanced matchmaking scenarios, queue rules can be configured.
We currently support these rule types:
String equality rule : ensures that a string attribute is the same across all tickets in a match.
Difference rule : ensures that the absolute difference for a number attribute between any two tickets in a
match is less than a configured maximum difference.
Set intersection rule : ensures that for a given attribute that is a list of strings, all tickets in a match share at
least as many values as is configured.
Match total rule : ensures that the sum of a number attribute across all players in a match is within a
configured range.
Region selection rule : ensures that the latency to a common data center for all users of the match is less
than a configured max value.
Team size balance rule : ensures that teams included in a match contain similar member counts.
Team difference rule : ensures that teams included in a match are within a configured difference for a
specific attribute (such as skill).
Team ticket size similarity rule : enforces that the number of large parties is equal to the number of
teams, or is zero.
Rules can be defined to enforce basic functionality, such as matching players with the same map, game mode or
game version. More advanced uses allow constraints to relax over time or become disabled after some time.
Such rules are useful for skill-based matchmaking. Visit Game Manager for more in-depth documentation on
these options.
For more information on specific flows from either your game client or service, see the following
documentation.
Quickstart guide
Quickstart - Client SDK
Quickstart - REST API
Configuration
Configuring matchmaking queues
Matchmaking scenario and configuration examples
Tutorials
Specifying attributes with your tickets
Displaying queue statistics in your title
Integrating with PlayFab Multiplayer Servers
Handling common error cases
Workaround for peer-to-peer connection
Using server backfill tickets
Analyzing Your Matchmaking Queue Usage
SDKs and Tools
Matchmaking API Reference (Public Preview)
PlayStream Events
matchmaking_match_found
matchmaking_ticket_completed
matchmaking_user_ticket_completed
matchmaking_user_ticket_invite
Public preview release notes
While PlayStream events are enabled, there is no currently integrated push notification system. As such, polling
is still the preferred method for checking the status of matchmaking a ticket.
Matchmaking Client SDK quickstart
5/24/2022 • 7 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

This quickstart guide walks you through the entire process for integrating the matchmaking feature in your title
code.
This tutorial illustrates how to submit a ticket to a specific queue in order to find a game. A queue likely maps to
a game mode or multiple game modes (ex.: a capture the flag mode and a king of the hill mode in the same
queue).
The matchmaking service handles finding a match amongst tickets in a queue. When a match is found, your title
must handle connecting the players together for gameplay.

Prerequisites
You need a PlayFab account to access Lobby and Matchmaking features.
Create/sign in to your PlayFab account. For instructions, see Quickstart: Game Manager.

Configure a matchmaking queue in Game Manager


The library matches users together who create tickets for queues that are configured in Game Manager. For
details on how to set one up, see Configuring matchmaking queues.

Download and set up the PlayFab Multiplayer Client SDK


Like the PlayFab Core SDKs, we have Multiplayer SDKs for different platforms and game engines. Select and
download the one that you need.
For download links, see Multiplayer SDKs.
For Unity and Unreal set up instructions, see the following articles.
Quickstart for Unity
Quickstart for Unreal

Initialize PlayFab Multiplayer Client SDK


Now that you've finished the setup, you're ready to make your first API call and use more Multiplayer features,
such as Matchmaking.
To start making Multiplayer API calls, you also need the PlayFab Entity Token. Get it via REST calls
(GetEntityToken) or by using the PlayFab Core SDK.
Once you have the entity token, initialize the Multiplayer library using PFMultiplayerInitialize and call
PFMultiplayerSetEntityToken to set the entity token for your local users.
Example using the Matchmaking client SDK
static PFMultiplayerHandle g_pfmHandle = nullptr;
...
...
HRESULT hr = PFMultiplayerInitialize(titleId, &g_pfmHandle);
RETURN_IF_FAILED(hr);

hr = PFMultiplayerSetEntityToken(g_pfmHandle, localUserEntity, entityToken);


RETURN_IF_FAILED(hr);

Create a matchmaking ticket


You create a matchmaking ticket using PFMultiplayerCreateMatchmakingTicket, in which you specify all local
users that should be part of the match and any attributes you want associated with those users.
This function also takes a PFMatchmakingTicketConfiguration where you specify which queue the ticket is for, a
timeout for the ticket, and any remote users that you want to match into this ticket.
Matchmaking with a single local user
You can start matchmaking for a single local user with a call to PFMultiplayerCreateMatchmakingTicket .

const char* yourQueueName = ...; // This is the name of the queue you configured in Game Manager.

PFMatchmakingTicketConfiguration configuration{};
configuration.timeoutInSeconds = 120;
configuration.queueName = yourQueueName;

const char* attributes = "\"{\"color\":\"blue\", \"role\":\"tank\"}\"";

const PFMatchmakingTicket* ticket;


HRESULT hr = PFMultiplayerCreateMatchmakingTicket(
g_pfmHandle,
1, // number of local users
localUserEntity,
&attributes,
&configuration,
nullptr, // optional asyncContext
&ticket);
RETURN_IF_FAILED(hr);

Matchmaking with a group of remote users


To start group matchmaking with remote users, it is helpful to think of one client as the leader. Have the leader
create the ticket using PFMultiplayerCreateMatchmakingTicket , specifying the other users in the group
through the configuration parameter. Once the ticket is created, call GetTicketId to get the ticket id. Transmit
this id to each other user through an external mechanism, such as a networking mesh or a shared PlayFab
Lobby, and have each client call PFMultiplayerJoinMatchmakingTicketFromId with the ticket id to join the
matchmaking ticket. The ticket status will be PFMatchmakingTicketStatus::WaitingForPlayers while waiting
for the specified players to join and will change to PFMatchmakingTicketStatus::WaitingForMatch once all
players have joined the ticket.
// Creating the ticket on the leader's client

const char* remoteMemberEntityId1 = ...;


const char* remoteMemberEntityId2 = ...;

std::vector<PFEntityKey> remoteMatchMemberEntityKeys;
remoteMatchMemberEntityKeys.push_back({ remoteMemberEntityId1, "title_player_account" });
remoteMatchMemberEntityKeys.push_back({ remoteMemberEntityId2, "title_player_account" });

const char* yourQueueName = ...; // This is the name of the queue you configured in Game Manager.

PFMatchmakingTicketConfiguration configuration{};
configuration.timeoutInSeconds = 120;
configuration.queueName = yourQueueName;
configuration.membersToMatchWithCount = 2; // number of remote members to match with
configuration.membersToMatchWith = remoteMatchMemberEntityKeys.data();

const char* attributes = "\"{\"color\":\"blue\", \"role\":\"tank\"}\"";

const PFMatchmakingTicket* ticket;


HRESULT hr = PFMultiplayerCreateMatchmakingTicket(
g_pfmHandle,
1, // number of local users
localUserEntity,
&attributes,
&configuration,
nullptr, // optional asyncContext
&ticket);
RETURN_IF_FAILED(hr);

// Getting the ticket id

PCSTR ticketId;
hr = PFMatchmakingTicketGetTicketId(ticket, &ticketId);
RETURN_IF_FAILED(hr);

// Joining the ticket on the other players' clients

const char* attributes = "\"{\"color\":\"blue\", \"role\":\"healer\"}\"";


const char* yourQueueName = ...; // This is the name of the queue you configured in Game Manager.

const PFMatchmakingTicket* ticket;


HRESULT hr = PFMultiplayerJoinMatchmakingTicketFromId(
g_pfmHandle,
1, // number of local users
localUserEntity,
&attributes,
ticketId,
yourQueueName,
nullptr, // optional asyncContext
&ticket);

Matchmaking with multiple local users


When matchmaking with multiple local users, instead of passing in one PFEntityKey to either the
PFMultiplayerCreateMatchmakingTicket or the PFMultiplayerJoinMatchmakingTicketFromId
functions, you need to pass in a list of keys. Similarly, you will need to pass in a list of attributes for each user.
Each list entry position should correspond with each other. Meaning that the first entry in attributes list should
be the attributes for the first player in the PFEntityKey list.
const char* yourQueueName = ...; // This is the name of the queue you configured in Game Manager.

PFMatchmakingTicketConfiguration configuration{};
configuration.timeoutInSeconds = 120;
configuration.queueName = queueName;

std::vector<PFEntityKey> localMatchMemberEntityKeys{ ... };


std::vector<PCSTR> localMatchMemberAttributes{ ... };

const PFMatchmakingTicket* ticket;


HRESULT hr = PFMultiplayerCreateMatchmakingTicket(
g_pfmHandle,
static_cast<uint32_t>(localMatchMemberEntityKeys.size())
localMatchMemberEntityKeys.data(),
localMatchMemberAttributes.data(),
&configuration,
nullptr, // optional asyncContext
&ticket);
RETURN_IF_FAILED(hr);

Check the status of the matchmaking ticket


You must poll for updates to the ticket by calling PFMultiplayerStartProcessingMatchmakingStateChanges to
receive state changes and then calling PFMultiplayerFinishProcessingMatchmakingStateChanges when you are
done processing those state changes.
The SDK will return a TicketStatusChanged state change any time the status of the ticket changes and a
TicketCompleted state change when matchmaking has completed.
Example using the Matchmaking client SDK
HRESULT hrTicketError = S_OK;

uint32_t stateChangeCount;
const PFMatchmakingStateChange * const * stateChanges;
hr = PFMultiplayerStartProcessingMatchmakingStateChanges(g_pfmHandle, &stateChangeCount, &stateChanges);
RETURN_IF_FAILED(hr);

for (uint32_t i = 0; i < stateChangeCount; ++i)


{
const PFMatchmakingStateChange& stateChange = *stateChanges[i];

switch (stateChange.stateChangeType)
{
case PFMatchmakingStateChangeType::TicketStatusChanged:
{
const auto& ticketStatusChanged = static_cast<const
PFMatchmakingTicketStatusChangedStateChange&>(stateChange);

PFMatchmakingTicketStatus status;
if (SUCCEEDED(PFMatchmakingTicketGetStatus(ticketStatusChanged.ticket, &status)))
{
printf("Ticket status is now: %i.\n", status);
}

break;
}
case PFMatchmakingStateChangeType::TicketCompleted:
{
const auto& ticketCompleted = static_cast<const PFMatchmakingTicketCompletedStateChange&>
(stateChange);

printf("PFMatchmaking completed with Result 0x%08x.\n", ticketCompleted.result);

if (FAILED(ticketCompleted.result))
{
// On failure, we must record the HRESULT so we can return the state change(s) and then bail
// out of this function.
hrTicketError = ticketCompleted.result;
}

break;
}
}
}

hr = PFMultiplayerFinishProcessingMatchmakingStateChanges(g_pfmHandle, stateChangeCount, stateChanges);


RETURN_IF_FAILED(hr);

// Now that we've returned the state change(s), bail out if we detected ticket failure.
RETURN_IF_FAILED(hrTicketError);

Get the match


After receiving the PFMatchmakingStateChangeType::TicketCompleted state change, call
PFMatchmakingTicketGetMatch to get the details of the match. This will contain the match id, the users who
have been matched together, and the preferred region for the match, and an arrangement string for lobby
associated with the match.
Once you have retrieved any information you need out of the PFMatchmakingMatchDetails struct, the ticket
should be destroyed with PFMultiplayerDestroyMatchmakingTicket.
Example using the Matchmaking client SDK
const PFMatchmakingMatchDetails* match;
HREULT hr = PFMatchmakingTicketGetMatch(ticket, &match);
RETURN_IF_FAILED(hr);

std::string matchId = match->matchId;


std::string lobbyArrangementString = match->lobbyArrangementString;

PFMultiplayerDestroyMatchmakingTicket(g_pfmHandle, ticket);

Cancelling a matchmaking ticket


If for some reason your client wants to cancel the matchmaking process prior to the timeout set in the
PFMatchmakingTicketConfiguration , call PFMatchmakingTicketCancel with the ticket handle.

Calling this doesn't guarantee the ticket will be canceled. The ticket could still complete before the cancelation
can be processed, or the cancelation request may fail due to networking or service errors. You should still
process matchmaking state changes to get the result of the ticket.
Example using the Matchmaking client SDK

HRESULT hr = PFMatchmakingTicketCancel(ticket);

(Optional) Connecting your players together into a Lobby


Once your players have matched, you will want to have them join each other. The
PFMatchmakingMatchDetails from the matched ticket contains a lobbyArrangementString field which can
be used to join the users into the same Lobby.
For more information about how Lobby and Matchmaking interact together, see Use lobby and matchmaking
together.
For more information about interacting with lobbies, see Lobby Documentation.
Example using the Matchmaking client SDK

const PFMatchmakingMatchDetails* match;


HREULT hr = PFMatchmakingTicketGetMatch(ticket, &match);
RETURN_IF_FAILED(hr);

std::string matchId = match->matchId;


std::string lobbyArrangementString = match->lobbyArrangementString;

PFMultiplayerDestroyMatchmakingTicket(g_pfmHandle, ticket);

PFLobbyHandle lobby;
RETURN_IF_FAILED_HR(PFMultiplayerJoinArrangedLobby(
m_pfmHandle,
&joiningUser,
lobbyArrangementString,
&joinConfig,
nullptr, // optional asyncContext
&lobby));

Conclusion
Using this quickstart, you should now have a successful matchmaking flow in your game. In addition, you
should consider the following:
How your title handles group formation.
What your title displays while users are waiting for a match.
How to handle failures and retries.
Matchmaking REST API quickstart
5/24/2022 • 5 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

This quickstart guide walks you through the entire process for integrating the matchmaking feature. All code
examples within this quickstart are for Unity - however, the concepts and flow apply (in general) to other
platforms as well.
Depending on your game design, consider the single user and multiple user matchmaking section.

NOTE
This guide assumes that you have already configured a matchmaking queue in Game Manager.

This tutorial illustrates how to submit a ticket to a specific queue in order to find a game. A queue likely maps to
a game mode or multiple game modes (ex.: a capture the flag mode and a king of the hill mode in the same
queue).
The matchmaking service handles finding a match amongst tickets in a queue. When a match is found, your title
must handle connecting the players together for gameplay.

Single user ticket matchmaking


If your game has a 1v1 game mode, or supports a single user entering matchmaking by themselves, consider
single user matchmaking. Single user matchmaking follows the pattern illustrated below.
Create a matchmaking ticket
A user creates a matchmaking ticket using CreateMatchmakingTicket. When ticket creation is successful, the
service returns a TicketId .
The ticket creation requires you to specify the Creator (the user's identity and attributes), GiveUpAfterSeconds
(the time in seconds before the service gives up on matching the ticket), and the QueueName in which to find a
match.
The Creator field must contain the user attributes required by the queue configuration matching the
QueueName . A good value for GiveUpAfterSeconds time is 120 seconds, to prevent users from giving up on their
own.

PlayFabMultiplayerAPI.CreateMatchmakingTicket(
new CreateMatchmakingTicketRequest
{
// The ticket creator specifies their own player attributes.
Creator = new MatchmakingPlayer
{
Entity = new EntityKey
{
Id = "<Entity ID goes here>",
Type = "<Entity type goes here>",
},

// Here we specify the creator's attributes.


Attributes = new MatchmakingPlayerAttributes
{
DataObject = new
{
Skill = 24.4
},
},
},

// Cancel matchmaking if a match is not found after 120 seconds.


GiveUpAfterSeconds = 120,

// The name of the queue to submit the ticket into.


QueueName = "myqueue",
},

// Callbacks for handling success and error.


this.OnMatchmakingTicketCreated,
this.OnMatchmakingError);

Check the status of the matchmaking ticket


You must poll the service by TicketId to access the Status of the ticket in matchmaking. In order to do so,
have your title call GetMatchmakingTicket. You can poll up to 10 times per minute. For instance, poll for the
ticket status every 6 seconds.
When the status of the ticket changes to Matched , your client can stop polling the ticket. From that point on, the
ticket will include the MatchId .
PlayFabMultiplayerAPI.GetMatchmakingTicket(
new GetMatchmakingTicketRequest
{
TicketId = "<ticket ID goes here>",
QueueName = "myqueue",
},
this.OnGetMatchmakingTicket,
this.OnMatchmakingError);

Get the match


From your client, call GetMatch with the MatchId provided in the response from GetMatchmakingTicket. This
match contains the list of users who are matched together.

PlayFabMultiplayerAPI.GetMatch(
new GetMatchRequest
{
MatchId = "<match ID goes here>",
QueueName = "myqueue",
},
this.OnGetMatch,
this.OnMatchmakingError);

Cancelling a matchmaking ticket


If for some reason your client wants to cancel the matchmaking process prior to GiveUpAfterSeconds being
reached, call CancelMatchmakingTicket with the TicketId . If a match hasn’t already been found, the ticket is
taken out of the matchmaking process and its status changes to Canceled .

PlayFabMultiplayerAPI.CancelMatchmakingTicket(
new CancelMatchmakingTicketRequest
{
QueueName = "myqueue",
TicketId = "<ticket ID goes here>",
},
this.OnTicketCanceled,
this.OnMatchmakingError);

Multiple user ticket matchmaking


If your game allows groups of players to go into a matchmaking queue together, there are a few more things
that need to be done to enter matchmaking. We advise that your title assigns a group leader (the creator), to
avoid making unnecessary calls. The leader creates the ticket, but all members of the group must consent to join
it.
Create a matchmaking ticket (multiple users)
The group must elect a ticket creator in your title. The creator creates a matchmaking ticket using
CreateMatchmakingTicket, which returns a TicketId upon success. The ticket creation requires you to specify
the Creator (the user's identity and attributes), GiveUpAfterSeconds (the time in seconds before the service
gives up on matching the ticket), MembersToMatchWith (the identities of the other group members) and the
QueueName in which to find a match.

The Creator field must contain the user attributes required by the queue configuration matching the
QueueName . A good value for GiveUpAfterSeconds time is 120 seconds, to prevent users from giving up on their
own.
Group members join the match ticket
Once the match ticket has been created, the other members of the group have to join it to move along the
matchmaking process. At this time, the ticket is in the WaitingForPlayers status. It will not begin matching with
other tickets until all MembersToMatchWith have joined the ticket.
To have members join, the Creator must share the TicketId to the other members through your title. Each
member then calls JoinMatchmakingTicket, providing their own required attributes. Once all members have
joined the ticket, the ticket status becomes WaitingForMatch .

PlayFabMultiplayerAPI.JoinMatchmakingTicket(
new JoinMatchmakingTicketRequest
{
TicketId = "<ticket ID>",
QueueName = "myqueue",
Member = new MatchmakingPlayer
{
Entity = new EntityKey
{
Id = "<Entity ID goes here>",
Type = "<Entity type goes here>",
},
Attributes = new MatchmakingPlayerAttributes
{
DataObject = new
{
Skill = 19.3
},
},
}
},
this.OnJoinMatchmakingTicket,
this.OnMatchmakingError);

The rest of the process is the same as that of single user ticket matchmaking
Connecting your players together
Once your players have matched, you will want to have them join each other - either through a server, or by
peer-to-peer connections.
If you are using a dedicated server, you can rely on the Match ID to uniquely identify the group of players they
should be in. If you are using PlayFab's multiplayer servers, GetMatch will provide a server and port for your
players to connect to.
Please refer to Integrating with PlayFab Multiplayer Servers for more information.
As of this release, peer-to-peer connection is currently not officially supported by matchmaking. If peer-to-peer
is required, consider using Playfab Party, or an interim workaround. Contact us for more support on this.

Conclusion
Using this quickstart, you should now have a successful matchmaking flow in your game. In addition, you
should consider the following:
How your title handles group formation.
What your title displays while users are waiting for a match.
How to handle failures and retries.
Known issues and limitations
In Public Preview, polling of tickets is required to obtain the match status and match ID. In the near future, we
will have a push mechanism for the clients to be updated on state changes.
The multi-user ticket flow will also be improved by the push mechanism. Follow the PlayFab blog for future
updates on improvements to matchmaking.
Matchmaking tutorials
5/24/2022 • 2 minutes to read • Edit Online

The tutorials in this section will guide you through a variety matchmaking topics.
Configuring matchmaking queues
Matchmaking scenario and configuration examples
Specifying attributes with your tickets
Displaying queue statistics in your title
Integrating with PlayFab Multiplayer Servers
Handling common error cases
Using server backfill tickets
Analyzing Your Matchmaking Queue Usage
Workaround for peer-to-peer connection
Configuring matchmaking queues
5/24/2022 • 8 minutes to read • Edit Online

Overview
Match configuration centers around queues, which represent a place where tickets wait to be matched with each
other. Each queue has some general configuration about what is required for a match. In addition, it can contain
a set of rules which provide further restrictions on how tickets are matched together.

Queue configuration
At the queue level, the configuration describes basic requirements regarding how tickets are matched inside a
queue, as well as how you obtain statistics information about the queue.
Queue name
The name for a specific queue. It is between 1 and 64 characters long (inclusive) and is case-sensitive. It is alpha-
numeric, plus underscores and hyphens, and starts with a letter or number. Generally a queue name represents
a way to play a game, such as "4v4CaptureTheFlag" or "UnrankedRace". When creating a matchmaking ticket,
the queue name must be specified to identify which queue it should enter.
Match size
The range of players allowed in a match. The minimum match size must be greater than or equal to 2, and the
maximum match size must be less than or equal to 100 (this limit is 32, if using teams).
In addition, even if a ticket alone already meets the minimum requirements for a match, it won't return a match
found until it matches at least one other ticket. If a ticket already meets the maximum requirement for a match,
however, it will be rejected.
Statistics available to players
This determines which queue statistics are exposed to players through the GetQueueStatistics API. Servers
always have access to all statistics. See the Displaying queue statistics in your title tutorial for more information.
There are two options you can control within this:
1. Show the number of players matching - Whether the number of players waiting for a match is exposed
to players. Titles may use this to hide the relative popularity of the mode, or to keep player counts hidden for
business reasons.
2. Show the time to match statistics - Whether the time to match statistics (average and percentiles) are
exposed to players.
Teams
A queue can include team configuration to have the match service assign players to teams. Additional team-
specific rules can be used to control how team assignment is done. Furthermore, the match service will ensure
that players matching together in the same ticket are not assigned to different teams.
You can have 2 or more teams defined in a queue.
Team name - The name used for this team. Team names are between 1 and 64 characters long (inclusive)
and are case-sensitive. They are alphanumeric, plus underscores and hyphens, and start with a letter or
number. In addition they must be unique within a queue.
Team size - Minimum and maximum number of players that can be on the team. Matchmaking will try to
form teams with as many players as possible up to the maximum.
Besides defining the teams and their sizes, additional rules can be enabled to help with how to handle teams in
matchmaking. See below for information on team-specific rules.

Rule configuration
Rules may be optionally defined for a queue. When configured, they help the matchmaking algorithm determine
which tickets should match together. Each rule applies to a single attribute in the player metadata. You can have
a maximum of 20 rules defined for a single queue.
There are many types of rules. Each contains some common configurable elements, as well as elements that are
specific to that particular type of rule. In addition, many rules allow an expansion, in which the rules become less
restrictive over time.
Common rule elements
The elements below are often used by all rules.
Rule Name - The name must be between 1 and 255 characters long (inclusive), is alpha-numeric plus
underscores and hyphens, and must start with a letter or number. Rule names must be unique within a
queue.
Weight - A way to modify the importance of a rule. Rules in general provide both a restriction as well as
a way to sort the remaining tickets that are eligible. The weight is a multiplier, modifying how important
the rule is for sorting purposes.
Attribute Source - Rules often act upon information that is provided to them. This field describes two
options for the source of this information:
1. User - Attributes are submitted alongside players in the create or join ticket request.
2. Player Entity - Attributes are retrieved from the player's associated Player Entity. These can be set via
the SetObjects API
Attribute Path - The path to reach the attribute. When using a User Attribute Source, it is simply the
name of the attribute. When using a Player Entity Attribute Source, it is a JSONPath that retrieves a
particular item from the entity, such as $.playerSkill.Mean .
Behavior when attribute is not specified - If a rule requires an attribute, but none is specified, the
rule may be configured with one of two behaviors:
1. It may supply a default value for the attribute.
2. It may use this as a signal to indicate the ticket meets any restriction supplied by the rule. This may be
useful if for instance, some players express a preference, and another player is willing to match
anyone. The player with no preference can neglect to supply an attribute, and match with any other
players.
Standard rule types
Each of the rule types is listed below, along with its purpose, some common uses, and any specific configuration
the rule may require.

RUL E T Y P E DESC RIP T IO N C O M M O N USES RUL E- SP EC IF IC F IEL DS

String Equality Ensures that a string Requires build versions or none


attribute is the same across other specific items to
all tickets in a match. match
RUL E T Y P E DESC RIP T IO N C O M M O N USES RUL E- SP EC IF IC F IEL DS

Difference Ensures that the absolute Groups players by skill, Merge function - Select
difference for a number experience, or other how multiple player values
attribute between any two numeric comparisons are merged into one value
tickets in a match is less representing the ticket.
than a configured maximum Choices are min, max, and
difference. average. Defaults to
average.

Set Intersection Ensures that for a given DLC or map selection Min intersection size -
attribute that is a list of Minimum number of shared
strings, all tickets in a match items for a match.
share at least as many
values as is configured.

Match Total Ensures that the sum of a Role selection, emulating Min/Max total - Sum of
number attribute across all host/server matchmaking, attribute must be within
players in a match is within adjusting player count these inclusive bounds.
a configured range. restrictions over time

Region Selection Ensures that the latency to Required for multiplayer Max Latency - Only
a common data center for server integration datacenters within this max
all users of the match is less latency are eligible for a
than a configured max match.
value.

Team rule types


Team rules can only be set if teams are present in the queue configuration. They provide additional ways to
require balance between the teams. The following team rules are available:

RUL E T Y P E DESC RIP T IO N C O M M O N USES RUL E- SP EC IF IC F IEL DS

Team Difference Ensures that teams included Balancing skills across none
in a match are within a teams
configured difference for a
specific attribute (such as
skills). This is very similar to
a standard Difference Rule,
except that the values
compared are each team's
average value.

Team Size Balance Ensures the difference in Player count balance across Allowed Team Size
player count between the teams Difference - How uneven
largest and smallest team the teams can be, as
does not exceed a measured by the difference
threshold. For instance, this in the number of players
rule could be used to create assigned to each one.
a queue where 3v3 and 4v4
matches are allowed, but a
3v4 is not.

Team Ticket Size Similarity Ensures that all teams Prevents parties (pre-made none
either have a large party, or teams) from matching with
do not have a large party. A a group of solo players.
large party is defined as at
least half of the maximum
team's size.
Expansions and becoming optional
Rules may become optional or less restrictive over time, allowing tickets that have waited for some time to
search wider for a potential match. There are two methods for controlling this behavior:
1. Seconds until optional - Simply indicates a length of time that the rule is active. The rule no longer
restricts matches among tickets that have waited this time.
2. Expansion process - Rules gradually adjust their configured thresholds over time. For instance, a
Difference Rule may require matches within a particular maximum difference. As a ticket waits, the rule
may expand the maximum difference, permitting expansion to a larger and larger range for the ticket,
and allowing it to be matched even if perfect opponents are unavailable.
Expansions can be either linear or custom . In a linear expansion, a value grows over time, using a fixed change
after each time interval. The items customized in a linear expansion are:
Seconds between expansions - How long in between each instance of the rule changing its restrictions.
Delta - The change of the value.
Limit - The end value. The rule never expands beyond this point.
In a custom expansion, the rule can use an arbitrary value each time the rule changes its restrictions. The
following fields are used:
Seconds between expansions - How long in between each instance of the rule changing its restrictions
One or more custom fields that modifies a rule during the expansion. Each field is semicolon delimited to
represent a different value which is used in each expansion's interval. The word "null" may be used in place of
a value to indicate the rule is not active during this interval.
The exact field modified depends on the rule. The following chart describes which rules have which kinds of
expansions, and what fields are modified by the expansion.

L IN EA R EXPA N SIO N C USTO M EXPA N SIO N AT T RIB UT E M O DIF IED


RUL E T Y P E A L LO W ED? A L LO W ED? DURIN G EXPA N SIO N

String Equality no yes Whether rule is active or


not

Difference yes yes Maximum allowed


difference

Set Intersection yes yes Minimum required


intersection

Match Total no yes Minimum and maximum


required totals

Region Selection yes yes Maximum allowed latency

Team Difference yes yes Allowed difference in team


values

Team Size Balance yes yes Allowed difference in


number of players per team

Team Ticket Size Similarity no no n/a

For more details on configuration use cases and examples, see Matchmaking scenario and configuration
examples.
Displaying queue statistics in your title
5/24/2022 • 2 minutes to read • Edit Online

Titles may sometimes wish to show how active their queues are, in an effort to set user expectations for wait
times. They may retrieve these statistics and display them directly to the user, or perhaps retrieve these statistics
from a server to display or collect approximated telemetry as they wish. This tutorial shows the steps for
retrieving these statistics from matchmaking.

Configure your queue


First, decide if you should configure your queue to allow statistics to be retrieved by users. Servers may always
retrieve statistics for each queue. Users may retrieve statistics only if the queue configuration has the Show the
number of players matching and/or Show the time to match statistics settings checked.
An example of a queue with this configuration can be found in the Matchmaking Configuration Examples.

Retrieving statistics
Call the GetQueueStatistics API to retrieve the statistics. These values are aggregated and updated over time. For
this reason, the GetQueueStatistics API should only be called intermittently. It is not intended to provide real-
time tracking of a queue's statistics.
Handling common error cases
5/24/2022 • 4 minutes to read • Edit Online

PlayFab matchmaking provides a simple interface for entering and leaving matchmaking. Despite this, there are
still multiple points where things may not go according to plan. Some of the more common error cases are
shown below, along with the ways a title should handle them.
This page assumes you are familiar with the general flow of PlayFab matchmaking. See our Matchmaking
quickstart for more information on the common use of matchmaking.

Errors on ticket creation


Ticket creation may fail for a number of reasons. In most of these cases, the PlayFab error code identifies
something invalid about the submission request. Correcting this will allow you to submit successfully.

NOTE
The errors MatchmakingAttributeInvalid and MatchmakingPlayerAttributesInvalid indicate an issue with the
formatting of attributes. See the section on Specifying Ticket Attributes for the details on how to pass attributes in a
ticket.

Other error codes indicate the request is valid, but circumstances outside the request prevent the ticket from
being accepted. In particular, these are:
1. - This indicates you have been submitting tickets too frequently. See the
MatchmakingRateLimitExceeded
section below for more details.
2. MatchmakingTicketMembershipLimitExceeded - This indicates the user is already in another active ticket. Users
are restricted from being in more than one ticket within a queue at a time, as they cannot play two games at
once. See the more detailed section below for more information on correcting this situation.
If you receive an HTTP error code of 503, simply retry your request after a brief delay.

Call returns MatchmakingRateLimitExceeded


Similar to other PlayFab features, PlayFab matchmaking will restrict the number of calls you make, according to
the limits configured inside the game manager. Receiving the MatchmakingRateLimitExceeded error indicates the
title has exceeded the limit for this call type.
In matchmaking, this most frequently occurs when polling GetMatchmakingTicket to see if a ticket has matched.
To avoid this error either increase your limit, or reduce your call frequency.

NOTE
Although the response will have an HTTP status code of 429, the request itself is valid and can still be retried.

Creating or joining a ticket returns


MatchmakingTicketMembershipLimitExceeded
In PlayFab matchmaking, a user can only be in one ticket at a time per queue, to avoid a case where a user
enters two matches and must decide which ticket to honor. Whichever match is not honored, it will be short a
player, and its players will likely be forced to re-enter matchmaking. The error
MatchmakingTicketMembershipLimitExceeded is returned if a user is already in one ticket that is neither canceled
nor matched, but tries to create or join another.
However, sometimes a title or server may lose track of a ticket, either by crashing, restarting, or other
unforeseen errors. When this occurs it will leave an active ticket that neither the user nor title is aware of.
This lost ticket prevents any future tickets from being submitted for this user until it expires. If this happens,
there are two options available to resolve the issue:
Option 1: Clear the ticket from matchmaking
Simply cancel all of a user's existing tickets. Calling CancelAllMatchmakingTicketsForPlayer will perform this
task. Afterwards matchmaking will have no tickets in progress, and be ready for a new ticket to be created.
Option 2: Find the lost ticket
Find the user's existing ticket and continue using it. Calling ListMatchmakingTicketsForPlayer will return all the
matchmaking ticket ids the user is a member of. Calling GetMatchmakingTicket on each ticketId provided will
allow you to retrieve its state and continue monitoring it until it finds a match.

Not all players join a multi-user ticket


When creating a multi-user ticket, one of the invited players may fail or refuse to join. In a case like this, the
created ticket will remain in the WaitingForPlayers status until it expires. Titles should expect this situation to
happen from time to time, and set a fairly short timeout within the UI.
After that timeout, the title should cancel the ticket and check that all players have still agreed to play a game
together.

GetMatch returns not found


Once a match is created, the match will live for a period of time and eventually age out. If the match is not
retrieved in time, those users will need to resubmit tickets to get matched again. This can be avoided by
ensuring matches are retrieved in a timely manner (i.e., within a few minutes).

The ticket is canceled


Tickets may be canceled for multiple reasons. The most common cases are user cancellations and tickets
expiring, but the ticket can also be canceled by the server. If you call GetMatchmakingTicket , and discover your
ticket is canceled, the reason will be listed in the CancellationReason field. Requested, Timeout, and Internal
correspond to user cancellation, ticket expiration, and server cancellation respectively.
In all cases, if the user still wishes to perform matchmaking, the title should simply submit another ticket.

Cancelling a ticket returns an error


Cancelling a ticket is not guaranteed to succeed. While most errors are self-explanatory, the error
MatchmakingTicketAlreadyCompleted indicates one of two possibilities:

1. The ticket was already canceled.


2. The ticket was already matched.
When receiving this error, titles should call GetMatchmakingTicket to differentiate between these two cases. In
the first case, the ticket is already in the desired state, and no further action needs to be taken. The second case
indicates that a user's cancellation was too late, and it has already matched. This race condition between a user's
cancellation and a match being found is unavoidable, and must be handled by the title.
The title has two options to resolve this--join the match anyway, disregarding the user's cancellation request, or
allow the match to begin knowing that a player will not join. Neither option is perfect, but it is important to
expect this situation to occur and consciously create a title flow for it. It is also worth noting that players may not
join a match for any number of reasons, so a title must handle this case regardless of the race condition
mentioned here.
Integrating with PlayFab Multiplayer Servers
5/24/2022 • 3 minutes to read • Edit Online

Matchmaking includes an option that can automatically create a game server for the resulting match. The
allocated server will run a build, which is configured in the queue's config. On startup, the server is passed in the
members of the match as the list of initial players.
A matchmaking queue is tied to a single multiplayer server build.

Requirements to use direct integration of matchmaking and servers


In order to allocate a multiplayer server from matchmaking, you will first need to configure a build and deploy
it. Follow the link we have provided here to get more information about that Multiplayer Server builds.
Matchmaking also needs a region selection rule to be added to the queue, so that matches can be allocated in
the optimal region for the build. The latency measurements passed into the region selection rule should match
the regions where the build is active. For more information on how to pass attributes to a region selection rule
see Region selection rule.

Activating server allocation for the queue


In order to enable server allocation for a queue, you will need to enable the checkbox for Enable ser ver
allocation on the queue config page, and provide the BuildId ( guid ) to associate with the queue. Once you
enable the feature, matchmaking will attempt to allocate a server for all the matches created within the queue.
The following example is what the config for a queue with multiplayer server integration should look like.

"MatchmakingQueue": {
"Name": "ServerEnabledQueue",
"MinMatchSize": 2,
"MaxMatchSize": 2,
"ServerAllocationEnabled": true,
"BuildId": "88b3e315-829c-4b6d-9872-74f427ad5331",
"Rules": [
{
"Type": "RegionSelectionRule",
"MaxLatency": 1000,
"Path": "Latencies",
"Weight": 1,
"Name": "RegionRule",
"SecondsUntilOptional": 60
}
]
}

The flow of calls to matchmaking remains the same with the server allocation enabled. Once matchmaking
allocates a server for the match, the resulting server details can be read from the Match object itself by calling
GetMatch.
A sample response is provided below for a GetMatch call for a queue with server allocation enabled.
{
"MatchId": "7c36330d-46b5-443f-8d8f-10390bce09d5",
"Members": [{
"TeamId": "",
"Entity": {
"Id": "67282A13A1A58910",
"Type": "title_player_account",
"TypeString": "title_player_account"
},
"Attributes": {
"DataObject": null,
"EscapedDataObject": "{\"StringEqualityRulePath\":\"0bc42969-76b1-4dcb-871d-d6e19cee741b\"}"
}
},
{
"TeamId": "",
"Entity": {
"Id": "6DB2B17FD21CC230",
"Type": "title_player_account",
"TypeString": "title_player_account"
},
"Attributes": {
"DataObject": null,
"EscapedDataObject": "{\"StringEqualityRulePath\":\"0bc42969-76b1-4dcb-871d-d6e19cee741b\"}"
}
}],
"RegionPreferences": ["WestUs", " EastUs"],
"ServerDetails": {
"IPV4Address": "40.76.31.170",
"Ports": [{
"Name": "game_port",
"Num": 30003
}]
}
}

The clients can use the IP and port from the server details section of the response to connect to the server. For
further information on how to connect clients to multiplayer servers, please refer to Connecting clients to
servers

NOTE
When a region of your build runs out of capacity, matchmaking will not be able to allocate matches for the queue in that
region. Matchmaking will keep retrying the allocation until the ticket expires. To increase multiplayer capacity, please refer
to Accessing increased core limits and additional Azure regions

Information passed to the game server


Here is the list of information that matchmaking will pass to the server.
SessionId - The SessionId for the server will be equal to the MatchId for the match.
InitialPlayers - This value is set to the list of members in the match. The list of players can be read in the
game by using the GSDK.
PreferredRegions - This field is set to the RegionPreferences field from the match. The game server service
will choose an appropriate region for the server from this list.
Matchmaking does not pass any ticket attributes to the game server. If the game needs to access any ticket
attributes on the server, it can do so by calling GetMatch with the ReturnMemberAttributes header to true .
Matchmaking scenario and configuration examples
5/24/2022 • 10 minutes to read • Edit Online

Overview
The system of queues and rules provides the flexibility to handle a large number of scenarios. Below are
examples of some of the more common matchmaking use cases, and their associated queues. Each of these can
be submitted directly via PlayFab APIs. These options can also be set via the Game Manager UI.

My first queue, or "quick match"


Every title should begin with this simple queue to work out their basic flows. This queue matches two players
together, and contains one optional rule that requires players to pass in the same build string in order to match.
If no build is specified, the player may match with other players in this queue, regardless of build.

"MatchmakingQueue": {
"Name": "MyFirstQueue",
"MinMatchSize": 2,
"MaxMatchSize": 2,
"ServerAllocationEnabled": false,
"Rules": [
{
"Type": "StringEqualityRule",
"Attribute": {
"Path": "Build",
"Source": "User"
},
"AttributeNotSpecifiedBehavior": "MatchAny",
"Weight": 1,
"Name": "BuildVersionRule"
}
]
}

Multiple game modes


Titles often have different ways to play games. If these players should never match with each other, placing them
in separate queues optimizes performance.

{
"MatchmakingQueue": {
"Name": "FreeForAllQueue",
"MinMatchSize": 4,
"MaxMatchSize": 4,
"ServerAllocationEnabled": false,
"Rules": [
]
}
}
{
"MatchmakingQueue": {
"Name": "CaptureTheFlagQueue",
"MinMatchSize": 4,
"MaxMatchSize": 4,
"ServerAllocationEnabled": false,
"Rules": [
]
}
}

Cross game mode search


If players are intended to match with others across game modes, use a single queue and create a Set
Intersection rule. Players can specify multiple game modes, and the rule will restrict matches to ones where all
players contain at least one common game mode.

NOTE
The number of players required to play must be the same across modes for this to function correctly.

{
"MatchmakingQueue": {
"Name": "MultiGameModeSearchQueue",
"MinMatchSize": 4,
"MaxMatchSize": 4,
"ServerAllocationEnabled": false,
"Rules": [
{
"Type": "SetIntersectionRule",
"MinIntersectionSize": 1,
"Attribute": {
"Path": "GameMode",
"Source": "User"
},
"AttributeNotSpecifiedBehavior": "MatchAny",
"Weight": 1,
"Name": "GameModeRule"
}
]
}
}

Skill based free-for-all game, with expansion


A very common scenario is attempting to match players together based on skill. In this example, the queue will
require players' skill attributes to be within 0.2, with these attributes increasing over time to 0.5. For tickets
waiting for more than 30 seconds, any skill difference is allowed.
The values for this example are chosen assuming the ranges of available skills are between 0 and 1. These
should be adjusted to fit the range of values your title uses to track the skills of its players, as well as how much
emphasis is placed on skill over the speed of a match.
In addition, the rule becoming optional at 30 seconds is intended for games where it is better to play a game
with unbalanced skills than to not play at all. For games where an unbalanced game is entirely a negative
experience, SecondsUntilOptional may be adjusted. If removed entirely, it causes the rule to remain active
indefinitely.
"MatchmakingQueue": {
"Name": "SkillBasedFreeForAllQueue",
"MinMatchSize": 4,
"MaxMatchSize": 4,
"ServerAllocationEnabled": false,
"Rules": [
{
"Type": "DifferenceRule",
"Difference": 0.2,
"MergeFunction": "Average",
"DefaultAttributeValue": 0.5,
"Expansion": {
"Delta": 0.1,
"Limit": 0.5,
"Type": "Linear",
"SecondsBetweenExpansions": 5
},
"Attribute": {
"Path": "Skill",
"Source": "User"
},
"AttributeNotSpecifiedBehavior": "UseDefault",
"Weight": 1,
"Name": "SkillRule",
"SecondsUntilOptional": 30
}
]
}

Customizing expansions
Expansions can be customized to use arbitrary values in each time interval. For instance, you may want the
allowed skill to grow slowly to start, and later grow increasingly quickly over time.
"MatchmakingQueue": {
"Name": "SkillBasedFreeForAllCustomExpansionQueue",
"MinMatchSize": 4,
"MaxMatchSize": 4,
"ServerAllocationEnabled": false,
"Rules": [
{
"Type": "DifferenceRule",
"Difference": 0.2,
"MergeFunction": "Average",
"DefaultAttributeValue": 0.5,
"Expansion": {
"DifferenceOverrides": [
0.025,
0.05,
0.1,
0.2,
0.3,
0.5
],
"Type": "Custom",
"SecondsBetweenExpansions": 5
},
"Attribute": {
"Path": "Skill",
"Source": "User"
},
"AttributeNotSpecifiedBehavior": "UseDefault",
"Weight": 1,
"Name": "SkillRule",
"SecondsUntilOptional": 30
}
]
}

Expansion of number of players over time


Some titles prefer having a full match to begin with, but over time may be satisfied with fewer and fewer people.
One such example is a Battle Royale style game, where it is preferred to start with as many as 50 players, but is
satisfied with fewer after some time.
As MinMatchSize and MaxMatchSize do not contain an expansion, a MatchTotalRule can be used to modify the
number of players required for a match. Each player specifies a value of 1 for the associated attribute, and the
rule sums these together to enforce a requirement on the number of players in a match that changes over time.

NOTE
Note that if a MaxOverrides or MinOverrides array is not specified, the rule's original Max or Min value will be used
in its place.
"MatchmakingQueue": {
"Name": "PlayerExpansionOverTime",
"MinMatchSize": 8,
"MaxMatchSize": 50,
"ServerAllocationEnabled": false,
"Rules": [
{
"Type": "MatchTotalRule",
"Attribute": {
"Path": "PlayerCount",
"Source": "User"
},
"Min": 8,
"Max": 50,
"Weight": 1,
"Expansion": {
"MinOverrides": [
50,
45,
40,
35,
25,
16,
8
],
"Type": "Custom",
"SecondsBetweenExpansions": 10
},
"Name": "PlayersRequiredRule",
"SecondsUntilOptional": 60
}
],
}

Standard 4v4 style skill based


PlayFab Matchmaking supports team-oriented matches. By specifying teams, players which are submitted
together in the same ticket will all be allocated into one team, and not be forced to play against each other.
PlayFab Matchmaking also supports various team rules to help ensure teams are balanced. The example shown
below is for a 4v4 match, and ensures the skills are balanced across them.
"MatchmakingQueue": {
"Name": "Standard4v4TeamsQueue",
"MinMatchSize": 8,
"MaxMatchSize": 8,
"ServerAllocationEnabled": false,
"Teams": [
{
"Name": "Red",
"MinTeamSize": 4,
"MaxTeamSize": 4
},
{
"Name": "Blue",
"MinTeamSize": 4,
"MaxTeamSize": 4
}
],
"Rules": [
{
"Type": "TeamDifferenceRule",
"Attribute": {
"Path": "Skill",
"Source": "User"
},
"Difference": 0.2,
"DefaultAttributeValue": 0.5,
"Expansion": {
"Delta": 0.1,
"Limit": 0.5,
"Type": "Linear",
"SecondsBetweenExpansions": 5
},
"Name": "TeamSkillRule",
"SecondsUntilOptional": 30
}
]
}

Multiplayer servers
A queue can automatically feed into PlayFab's multiplayer servers feature, allocating a server and feeding it a list
of matched players. This queue provides the smallest example of such a config, which is the
ServerAllocationEnabled flag, along with the BuildId representing what build of the server should be started.

When the ServerAllocationEnabled flag is set to true ,a RegionSelectionRule is also required to indicate where
a server should be allocated for each match.
"MatchmakingQueue": {
"Name": "MultiplayerServersQueue",
"MinMatchSize": 24,
"MaxMatchSize": 24,
"ServerAllocationEnabled": true,
"BuildId": "6a4d2760-4295-417e-b149-0a12e3570d94",
"Rules": [
{
"Type": "RegionSelectionRule",
"MaxLatency": 200,
"Path": "Latency",
"Weight": 1,
"Name": "RegionSelectionRule"
}
]
}

Big Team Battle (12 vs 12)


Larger team games may have additional requirements. In this example, the queue is configured to create a
multiplayer server, which is often required to manage games with this many players. This is similar to the
example above.
In addition to skill, another Team Rule is added to encourage team similarity--only one large team is allowed on
each side, preventing a common situation of a Premade team being matched against a large set of random
players.
"MatchmakingQueue": {
"Name": "LargeTeamsQueue",
"MinMatchSize": 24,
"MaxMatchSize": 24,
"ServerAllocationEnabled": true,
"BuildId": "6a4d2760-4295-417e-b149-0a12e3570d94",
"Teams": [
{
"Name": "Red",
"MinTeamSize": 12,
"MaxTeamSize": 12
},
{
"Name": "Blue",
"MinTeamSize": 12,
"MaxTeamSize": 12
}
],
"Rules": [
{
"Type": "TeamTicketSizeSimilarityRule",
"Name": "PreventLargePremadeVersusRandomsRule",
"SecondsUntilOptional": 20
},
{
"Type": "TeamDifferenceRule",
"Attribute": {
"Path": "Skill",
"Source": "User"
},
"Difference": 0.1,
"DefaultAttributeValue": 0.5,
"Expansion": {
"Delta": 0.1,
"Limit": 0.5,
"Type": "Linear",
"SecondsBetweenExpansions": 5
},
"Name": "TeamSkillRule",
"SecondsUntilOptional": 30
},
{
"Type": "RegionSelectionRule",
"MaxLatency": 200,
"Path": "Latency",
"Weight": 1,
"Name": "RegionSelectionRule"
}
]
}

Battle Royale
Battle Royale games place many people into an arena. In this example, the game is set up with teams of four.
Currently there is a limit of 32 players allowed in a team scenario such as this one - This limitation will be
improved in the future.
This example also contains multiplayer server setup information for dedicated servers, which is often necessary
for games with large numbers of players. This is similar to the example shown above.
"MatchmakingQueue": {
"Name": "BattleRoyaleStyleQueueWithTeams",
"MinMatchSize": 32,
"MaxMatchSize": 32,
"ServerAllocationEnabled": true,
"BuildId": "6a4d2760-4295-417e-b149-0a12e3570d94",
"Teams": [
{
"Name": "team1",
"MinTeamSize": 4,
"MaxTeamSize": 4
},
{
"Name": "team2",
"MinTeamSize": 4,
"MaxTeamSize": 4
},
{
"Name": "team3",
"MinTeamSize": 4,
"MaxTeamSize": 4
},
{
"Name": "team4",
"MinTeamSize": 4,
"MaxTeamSize": 4
},
{
"Name": "team5",
"MinTeamSize": 4,
"MaxTeamSize": 4
},
{
"Name": "team6",
"MinTeamSize": 4,
"MaxTeamSize": 4
},
{
"Name": "team7",
"MinTeamSize": 4,
"MaxTeamSize": 4
},
{
"Name": "team8",
"MinTeamSize": 4,
"MaxTeamSize": 4
}
],
"Rules": [
{
"Type": "RegionSelectionRule",
"MaxLatency": 200,
"Path": "Latency",
"Weight": 1,
"Name": "RegionSelectionRule"
}
]
}

Cross-Device / Cross Platform


To limit games of a particular device or platform to match with each other, specify the device with a String
Equality Rule. With the AttributeNotSpecifiedBehavior of MatchAny , tickets that do not specify such a device can
opt to match with any device/platform. If matchmaking times are longer than expected, consider creating a
separate queue per platform, with a cross-platform queue as needed to support cross-play.

"MatchmakingQueue": {
"Name": "CrossDeviceQueue",
"MinMatchSize": 32,
"MaxMatchSize": 32,
"ServerAllocationEnabled": false,
"BuildId": "6a4d2760-4295-417e-b149-0a12e3570d94",
"Rules": [
{
"Type": "StringEqualityRule",
"Attribute": {
"Path": "DeviceType",
"Source": "User"
},
"AttributeNotSpecifiedBehavior": "MatchAny",
"Weight": 1,
"Name": "CrossDeviceRule"
}
]
}

Host/Searcher or Role Based Requirements


PlayFab Match uses a ticket-based matching system, where a game host is not selected ahead of time. However,
it can emulate a host-searcher system by using a MatchTotalRule to limit the number of hosts allowed in a
match.
Tickets can then specify ahead of time if it is a host by specifying 1. Each match must contain exactly one host.

NOTE
If the number of hosts vastly outnumbers the searchers or vice-versa, this may cause slow matchmaking times for all
players. Consider the implications of your matchmaking design to ensure there are enough players in any given
subpopulation to satisfy your matchmaking rules and the desired average time to match.

"MatchmakingQueue": {
"Name": "HostSearcherQueue",
"MinMatchSize": 8,
"MaxMatchSize": 8,
"ServerAllocationEnabled": false,
"BuildId": "6a4d2760-4295-417e-b149-0a12e3570d94",
"Rules": [
{
"Type": "MatchTotalRule",
"Attribute": {
"Path": "IsHost",
"Source": "User"
},
"Min": 1,
"Max": 1,
"Weight": 1,
"Name": "OneHostRule"
}
]
}

Games may have role requirements - for instance, a game may require one drummer, two guitarists, and one
vocalist. Or one tank, two DPS, and one support. Games may use the MatchTotalRule to require these roles as
shown below.
"MatchmakingQueue": {
"Name": "RoleBasedQueue",
"MinMatchSize": 4,
"MaxMatchSize": 4,
"ServerAllocationEnabled": false,
"BuildId": "6a4d2760-4295-417e-b149-0a12e3570d94",
"Rules": [
{
"Type": "MatchTotalRule",
"Attribute": {
"Path": "TankSelected",
"Source": "User"
},
"Min": 1,
"Max": 1,
"Weight": 1,
"Name": "TankRule"
},
{
"Type": "MatchTotalRule",
"Attribute": {
"Path": "DPSSelected",
"Source": "User"
},
"Min": 2,
"Max": 2,
"Weight": 1,
"Name": "DPSRule"
},
{
"Type": "MatchTotalRule",
"Attribute": {
"Path": "SupportSelected",
"Source": "User"
},
"Min": 1,
"Max": 1,
"Weight": 1,
"Name": "SupportRule"
}
]
}

Rules with varying importance


Rules guide matchmaking by both restricting what tickets are eligible to match with another, and choosing the
order in which those tickets are picked. When multiple rules are present, all their restrictions are taken into
account. However, a title may wish to give more priority to a rule's preference over the remaining eligible tickets.
In the example below, a player must be within a skill and experience level. However, if there are many tickets
within the designated skill and experience boundaries, this queue prefers the ones closer in skill as opposed to
the ones closer in experience level.
Skill differences are counted three times as much as experience differences, when evaluating the tickets that
have met the restrictions.
"MatchmakingQueue": {
"Name": "WeightingQueue",
"MinMatchSize": 4,
"MaxMatchSize": 4,
"ServerAllocationEnabled": false,
"BuildId": "6a4d2760-4295-417e-b149-0a12e3570d94",
"Rules": [
{
"Type": "DifferenceRule",
"Difference": 1,
"MergeFunction": "Average",
"Attribute": {
"Path": "skill",
"Source": "User"
},
"AttributeNotSpecifiedBehavior": "MatchAny",
"Weight": 3,
"Name": "SkillRule"
},
{
"Type": "DifferenceRule",
"Difference": 5,
"MergeFunction": "Average",
"Attribute": {
"Path": "experience",
"Source": "User"
},
"AttributeNotSpecifiedBehavior": "MatchAny",
"Weight": 1,
"Name": "ExperienceRule"
}
]
}

DLC packs
With various DLC packs, players may opt to only find other players that have a matching DLC, using a
SetIntersectionRule . Each player passes in the DLC packs they own, and a match requires a group to share at
least one DLC pack.

NOTE
After 30 seconds, the rule becomes optional, allowing players to match without sharing DLC.
"MatchmakingQueue": {
"Name": "DlcQueue",
"MinMatchSize": 4,
"MaxMatchSize": 4,
"ServerAllocationEnabled": false,
"BuildId": "6a4d2760-4295-417e-b149-0a12e3570d94",
"Rules": [
{
"Type": "SetIntersectionRule",
"MinIntersectionSize": 1,
"Attribute": {
"Path": "DlcPacks",
"Source": "User"
},
"AttributeNotSpecifiedBehavior": "MatchAny",
"Weight": 1,
"Name": "DlcRule",
"SecondsUntilOptional": 30
}
]
}

Enabling Statistics
Enabling statistics allows your title to display information about a queue. This information can be useful for
setting player expectations as they choose a game mode they would like to play.
Conversely, titles may wish to hide this information - either for business intelligence purposes, or to avoid
directing players into high-traffic queues.
The queue below enables both the ability to see the number of players present in a queue and an estimated time
a ticket takes to match.

NOTE
A server may always retrieve this information - the configuration shown below only controls whether users are allowed to
make this call as well.

"MatchmakingQueue": {
"Name": "StatisticsEnabledQueue",
"MinMatchSize": 8,
"MaxMatchSize": 8,
"ServerAllocationEnabled": false,
"Rules": [],
"StatisticsVisibilityToPlayers": {
"ShowNumberOfPlayersMatching": true,
"ShowTimeToMatch": true
}
}
Specifying attributes with your tickets
5/24/2022 • 2 minutes to read • Edit Online

Rules determine which tickets are matched, based on the attributes specified by players. These attributes can be
specified in two ways, either:
1. Within the create ticket request
2. In the player's entity
This tutorial describes how to specify those attributes.

Specifying within the create ticket request


For rules configured with the attribute type "User", attributes are specified in a CreateMatchmakingTicket request,
alongside the player entity inside of an attributes DataObject .

POST https://{{TitleId}}.playfabapi.com/Match/CreateMatchmakingTicket
{
"Creator": {
"Entity": {
"Id": "A8140AB9109712B",
"Type": "title_player_account",
"TypeString": "title_player_account"
},
"Attributes": {
"DataObject": {
"mu": 16.0,
"sigma": 1.8,
"nestExample": {
"exp": 1500
}
}
}
},
"MembersToMatchWith": [],
"GiveUpAfterSeconds": 2,
"QueueName": "SkillRuleQueue"
}

Below is an example queue configuration with a DifferenceRule . This rule contains an attribute path and source
that will pick up the value 16.0, specified by the CreateMatchmakingTicket request above.
"MatchmakingQueue": {
"Name": "SkillRuleQueue",
"MinMatchSize": 2,
"MaxMatchSize": 2,
"ServerAllocationEnabled": false,
"Rules": [
{
"Type": "DifferenceRule",
"Difference": 3,
"MergeFunction": "Average",
"Attribute": {
"Path": "mu",
"Source": "User"
},
"AttributeNotSpecifiedBehavior": "MatchAny",
"Weight": 1,
"Name": "SkillRule",
"SecondsUntilOptional": 10
}
]
}

NOTE
Rules can navigate through the DataObject with a JSON Path. Replacing the Path field with "nestExample.exp" would
cause the rule to use the value 1500 for the ticket created above.

Specifying through player entities


For rules with the attribute type "Player Entity", attributes are specified through a separate call to the
SetObjects API.

This allows data to be stored for a user, rather than the title needing to specify it on each create ticket call. This
may make more sense for values that persist for a user, or that users cannot be trusted to submit. An example of
this SetObjects call is shown below.

POST https://{{TitleID}}.playfabapi.com/Object/SetObjects
{
"Objects": [
{
"ObjectName": "playerSkill",
"DataObject": {
"skillDetail": {
"mu": 16.0,
"sigma": 2.0
}
}
}
],
"Entity": {
"Id": "A8140AB9109712B",
"Type": "title_player_account",
"TypeString": "title_player_account"
}
}

A queue with the following configuration would retrieve the value 16.0 for use in its DifferenceRule rule, when
a ticket is created with this player.
NOTE
In the Path field, the first item after the root is the ObjectName , allowing you to choose which stored object to
reference.

"MatchmakingQueue": {
"Name": "PlayerEntityRuleQueue",
"MinMatchSize": 2,
"MaxMatchSize": 2,
"ServerAllocationEnabled": false,
"Rules": [
{
"Type": "DifferenceRule",
"Difference": 1,
"MergeFunction": "Average",
"Attribute": {
"Path": "$.playerSkill.skillDetail.mu",
"Source": "PlayerEntity"
},
"AttributeNotSpecifiedBehavior": "MatchAny",
"Weight": 1,
"Name": "SkillRule",
"SecondsUntilOptional": 10
}
]
}

Special formats
Most rules use attributes that are either strings or numeric, and are simply those values in JSON format. Rules
that require more complex attributes to be passed in are listed below.
Region Selection rule
A Region Selection rule requires an array of latency measurements with the specified schema. The following
example is the expected attribute format for a region selection rule, shown alongside the two attributes used in
the CreateMatchmakingTicket request example for comparison.
POST https://{{TitleId}}.playfabapi.com/Match/CreateMatchmakingTicket
{
"Creator": {
"Entity": {
"Id": "A8140AB9109712B",
"Type": "title_player_account",
"TypeString": "title_player_account"
},
"Attributes": {
"DataObject": {
"mu": 16.0,
"sigma": 1.8,
"Latencies": [
{
"region": "EastUs",
"latency": 150
},
{
"region": "WestUs",
"latency": 400
}
]
}
}
},
"MembersToMatchWith": [],
"GiveUpAfterSeconds": 2,
"QueueName": "ServerEnabledQueue"
}

In this example, Latencies must match the field referenced by the Path field in the rule. An example of a rule
which would use the Latencies field is included in the queue below.

"MatchmakingQueue": {
"Name": "ServerEnabledQueue",
"MinMatchSize": 2,
"MaxMatchSize": 2,
"ServerAllocationEnabled": true,
"BuildId": "88b3e315-829c-4b6d-9872-74f427ad5331",
"Rules": [
{
"Type": "RegionSelectionRule",
"MaxLatency": 1000,
"Path": "Latencies",
"Weight": 1,
"Name": "RegionRule",
"SecondsUntilOptional": 60
}
]
}

NOTE
When using the region selection rule for a queue that has server allocation enabled, the regions must be valid Azure
Regions. You can find the list of valid Azure Regions here.
Using server backfill tickets
5/24/2022 • 4 minutes to read • Edit Online

Games hosted on a server sometimes find they need to search for additional players. Most often this occurs
when one or more players disconnect while the game is in progress. Server backfill tickets allow a game server
to search for additional players which will fit into the game currently being played.
Server backfill tickets differ from regular matchmaking tickets in multiple ways:
1. Matching
Backfill tickets cannot match with each other.
Backfill tickets are given priority during searching. This reduces fragmentation of the player base.
2. Contract
Backfill tickets may be created with a ServerDetails field. This allows the server to indicate how
matched players should connect to it.
Backfill tickets may be created with team assignments. This allows games with teams to maintain their
team information.
3. Queue properties
Backfill tickets do not trigger Multiplayer Server allocation.
Backfill tickets are not reflected in queue statistics, as their players are already playing a game and
would inaccurately skew wait time.
4. Ownership
Backfill tickets are owned by a game server, not a user. Users cannot view or interact with backfill
tickets in any way.

Creating a server backfill ticket


The backfill process begins similarly to creating a regular matchmaking ticket, but with the
CreateServerBackfillTicket call as opposed to a CreateServerMatchmakingTicket call. The game server must
supply all member information for the game it is currently hosting. This is most efficiently done by storing the
attributes returned in the prior match result. These attributes can be retrieved by calling GetMatch with the
ReturnMemberAttributes flag. Alternatively the game server may query the users for attribute information.

In addition to the members, the game server may specify two additional pieces of information.
ServerDetails
This structure is identical to the structure returned in a GetMatch call, and allows the server to specify any
information required to connect to it. When the backfill ticket is matched, its ServerDetails structure will be
returned to any players who call GetMatch on the resulting match. All fields in this structure are optional. Titles
may only need a subset of these in order to provide enough information for clients to connect to the game
server.

NOTE
The IPV4Address field is not validated and may be used to supply arbitrary connection string information to clients.
{
"ServerDetails": {
"IPV4Address": "123.234.123.234",
"Ports": [
{
"Port": {
"Name": "portname",
"Num": 12345,
"Protocol": "UDP"
}
}
],
"Region": "EastUS"
}
}

Team Assignments
If the backfill ticket is submitted to a queue with teams, each member may also be specified with a TeamId,
indicating the team they are currently on. This membership will be preserved when a Match is returned. If a
TeamId is not specified for a user, it may be placed on any team.

{
"Members": [
{
"TeamId": "red",
"Entity": {
"Id": "6570DE3537DC9DF6",
"Type": "title_player_account",
"TypeString": "title_player_account"
},
"Attributes": {
"DataObject": {
"Skill": 25
}
}
}
]
}

Interacting with a backfill ticket


Once created, a backfill ticket begins searching for regular matchmaking tickets which meet the rule criteria. The
flow for backfill tickets is identical to how regular matchmaking tickets operate, except with analagous APIs. The
game server may check the status of its ticket by calling GetServerBackfillTicket. It may also cancel the ticket by
calling CancelServerBackfillTicket.

NOTE
Clients are not allowed to cancel a backfill ticket they are in. Suppose a client was in a 4v4 match, and a player on the
opposing team dropped. The client could maintain its advantage by continously canceling any backfill tickets it was in. To
prevent this, only game servers may cancel backfill tickets.

Membership limits and recovering from lost backfill tickets


Similar to regular matchmaking tickets, at any time a user may be in only one backfill ticket per queue. This limit
is tracked separately from the regular tickets which a client controls.
In the case where a game server creates a backfill ticket and then crashes, any users in the lost backfill ticket will
be unable to be submitted in another backfill ticket due to the membership limit. A game server will discover
this by receiving the error MatchmakingTicketMembershipLimitExceeded , along with a list of users indicating which
have outstanding backfill tickets in an errorDetails body.

{
"code": 400,
"status": "BadRequest",
"error": "MatchmakingTicketMembershipLimitExceeded",
"errorCode": 2055,
"errorMessage": "User is a member of too many backfill tickets.",
"errorDetails": {
"UsersExceedingMembershipLimit": [
"title_player_account!562D72A5B184F612"
]
}
}

The game server can recover a user from this situation by calling CancelAllServerBackfillTicketsForPlayer, which
removes all backfill tickets the user is in. ListServerBackfillTicketsForPlayer is also provided as a method to
discover which backfill tickets a player may be in.

Interactions with the Region Selection Rule


The Region Selection rule normally requires that tickets specify an array of latency measurements for its
attribute. A backfill ticket, however, represents a game already in progress in a particular datacenter. Instead of
an array of latency measurements, the create request must specify a Region in the ServerDetails structure. For
tickets to match with the backfill ticket, they must have an acceptable ping time to the region specified by the
backfill ticket.

Interactions with the Team Ticket Size Similarity Rule


The Team Ticket Size Similarity Rule enforces that large groups of players are matched against other large
groups of players. However, backfill tickets do not contain the information of which players joined the game as a
group. As such, the Ticket Size Similarity Rule is ignored when matching backfill tickets.
Matchmaking Queue Usage
5/24/2022 • 3 minutes to read • Edit Online

PlayFab matchmaking provides charts that help developers understand their customer's matchmaking usage
patterns. The Matchmaking Usage view can be accessed within the GameManager portal under the Muliplayer-
>Matchmaking tab. Once a specific queue is selected, there will appear a "Usage" sub tab adjacent to the "Edit
Queue" sub tab. As long as matchmaking activity is occuring in that queue, selecting the Usage tab will render
various charts that depict matchmaking activity (or possibly lack thereof) within it.

Charts
Each of the charts described below can render data over the past hour, 4 hours, day, 3 days, week, or month (4
weeks). To change the time window, click the time duration dropdown and select a different time window. All
graphs will render using the same time window.
Average Matchmaking Time
This chart shows how long it takes for a match to be found in this matchmaking queue. If the time seems to take
longer than expected, it's worth re-examining the rules for this queue to see if those rules are overly restrictive
resulting in longer matchmaking times. It also is worth looking at the other charts to see how active this queue
is and if other issues may be preventing timely matches.

Y-Axis: seconds

Average Time to Cancel a Ticket


This chart shows how long it takes to cancel a ticket. Tickets can be canceled by the matchmaking service or by
players. This graph can be used in conjuction with the Canceled Ticket Rate graph to better understand not only
how long tickets take to be canceled, but what is driving those cancellations and how many of each cancellation
type is happening.

Y-Axis: seconds

Match Completion Rate


This chart shows how frequently matches are found for players in that matchmaking queue. If the rate is lower
than expected or bouncing off of zero, that may indicate either an issue with the matchmaking service, or how
the matchmaking queue rules are configured. This graph can be used in conjunction with the "Average
Matchmaking Time" graph to acertain how successfully matches in this queue are occuring (or not).

Y-Axis: # of completed matches /sec

Canceled Ticket Rate


This chart shows the rate of ticket cancellations within this matchmaking queue, and also shows what
cancellation types are occuring by kind. If matches are not happening as quickly or frequently as expected, this
graph may indicate a higher than expected rate of ticket cancellations that is hindering the matchmaking
process.
Cancellation Types
Each of the ticket cancellation types is listed below, along with its purpose and what entity initiated it.

C A N C EL L AT IO N T Y P E DESC RIP T IO N O RIGIN

Requested A user manually canceled a ticket from User


this queue's matchmaking process.

Timeout The matchmaking process for this Server


ticket exceeded its maximum
configured time to find a match.

TicketUnmatchable The ticket in this queue will never find Server


a match based on its current queue
rules.

ServerAllocationFailed A match was successfully created, but Server


for some reason could not be allocated
to a PlayFab server.

Internal An unknown internal error occurred. If Server


these errors occur often, please
contact support.

Y-Axis: ticket cancellations /sec

Tickets Waiting for a Match


This chart shows how many tickets are still waiting to be matched with other tickets in that queue. If this number
is low, it may indicate that the matchmaking queue is not popular with users, but alternatively could indicate that
new matches are occuring very quickly in this queue. If this number is high, it is worth looking at the "Average
Matchmaking Time" graph to see if the high number is related to a slow matchmaking process in this queue, or
if this queue is merely popular with players.

Y-Axis: # of waiting tickets

Other Common Issues Identified with Matchmaking Usage Data


As mentioned in some of the chart descriptions above, charts can be used and cross-referenced to pinpoint
issues with matchmaking queues. The following table suggests how to use one or more charts to quickly
diagnose common problems.
ISSUE P RO B A B L E M EA N IN G

Zero or erratic match completion rate Queue configured incorrectly, queue doesn't match with title

Low match completion rate, long matchmaking times Queue rules are too restrictive

High match completion rate, high ticket cancellation rate Quitters, unsatisfactory matches
Workaround for peer-to-peer connection
5/24/2022 • 2 minutes to read • Edit Online

The end result of matchmaking is a Match - a collection of tickets that satisfy the rules for the queue. For titles
with a dedicated server, the match ID is unique, and can be used to identify groups of players that should play
together.
In the peer-to-peer case however, the title needs to pass connection information to each other. This tutorial
describes a workaround to perform this.

NOTE
Peer-to-peer connection in matchmaking is currently not officially supported. Consider PlayFab Party, or contact us for
more information.

Specify an IP address as an attribute


Similar to Specifying attributes with your tickets, an arbitrary value such as an IP address can be specified as an
attribute. It does not need to correspond to a rule.

POST https://{{TitleId}}.playfabapi.com/Match/CreateMatchmakingTicket
{
"Creator": {
"Entity": {
"Id": "A8140AB9109712B",
"Type": "title_player_account",
"TypeString": "title_player_account"
},
"Attributes": {
"DataObject": {
"IP": "123.234.123.12"
}
}
},
"MembersToMatchWith": [],
"GiveUpAfterSeconds": 2,
"QueueName": "IPExampleQueue"
}

Retrieving all player IPs from a Match


When calling GetMatch, specify the flag ReturnMemberAttributes as true to have the attributes of each ticket
returned. This will include the specified IP addresses.
{
"code": 200,
"status": "OK",
"data": {
"MatchId": "3d58dc0f-2eb6-4162-a2e0-1ed6ac5ea551",
"Members": [
{
"TeamId": "",
"Entity": {
"Id": "A8140AB9109712B",
"Type": "title_player_account",
"TypeString": "title_player_account"
},
"Attributes": {
"DataObject": {
"IP": "123.234.123.12"
}
}
},
{
"TeamId": "",
"Entity": {
"Id": "562D72A5B184F612",
"Type": "title_player_account",
"TypeString": "title_player_account"
},
"Attributes": {
"DataObject": {
"IP": "123.234.123.12"
}
}
}
]
}
}

NOTE
While this can be used to exchange IPs, it does not guarantee connectivity between the clients.
Lobby and Matchmaking real-time notifications
5/24/2022 • 2 minutes to read • Edit Online

Overview
The Matchmaking and Lobby features have built in support for real-time notifications. Notifying players of
changes to Matchmaking or Lobby has never been easier, as the work to handle notifications is done for you.
New APIs will allow connected clients to subscribe for notifications of Lobby and Matchmaking changes. With
this addition, you'll no longer need to poll for changes to matches or lobbies.
The client SDK has been designed to simplify your work. The client SDK manages calls between clients and
Lobby and Matchmaking services. It handles the delivery of notifications from those services to connected
clients in real time. Real-time notifications have cross-platform support, and will work anywhere PlayFab
supplies a client SDK. Matchmaking and Lobby can be used separately or together, and real-time notifications
will work in either case. There's no support for real-time notifications without the client SDK at this time. Real-
time notifications aren't available as a solution for stand-alone or general use.

How do real-time notifications work


Each client maintains a single WebSocket to receive real-time notifications. When there are updates to
Matchmaking or Lobby resources in the cloud, the client SDK will forward notifications in real-time to all
connected clients subscribed to those resources.
When a client connects to receive real-time notifications, they'll open a new WebSocket connection to receive
notifications and listen for change events. When a client creates a lobby, joins a lobby, starts listening for
invitations, or creates a Matchmaking ticket, the connected client will subscribe to a Lobby or Matchmaking
resource to listen for changes. The client will be notified when there's an update on the resource topic they’ve
subscribed to. For example, if a client has subscribed to a Lobby resource, they may be notified on change
events like Player A or B has joined or left a Lobby. Matchmaking and Lobby documentation describe in more
detail the operations that will power notifications.
The WebSocket connection that enables real-time notifications is also used for detecting client connectivity. This
client connectivity status is used by the Lobby service to power lobby ownership management.

Shared connection support


Matchmaking and Lobby notifications have support to share a single WebSocket connection, which may be
useful if you’re creating a title with couch co-op. Today, up to eight local users may share the WebSocket
connection, and local players can be added or removed to that shared connection. Multiple users sharing the
same connection can subscribe to topics to get notifications for Matchmaking or Lobby events for those topics.

Using the client SDK


The client SDK simplifies your work for cross-network and cross-platform play by handling real-time
notifications for you. Notifications are sent to clients on receiving invites, joining and updating lobbies, finding
matches, and more. The client SDK enables cross-platform play and real-time notifications on any platform that
PlayFab offers SDK support. Sending notifications to clients is automatic, and the developer doesn't have to do
any work to enable notifications.
Azure PlayFab Lobby overview
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

Azure PlayFab Lobby is a service to create a temporary grouping mechanism for players to play games together.
It's frequently used with matchmaking after finding people to play with.

Benefits
Cross-platform scalable lobby service
Highly customizable to support a wide variety of gameplay needs
Use seamlessly with PlayFab LiveOps and backend services. This includes PlayFab Matchmaking, PlayFab
Multiplayer Servers, and PlayFab Party
Client SDK support for real-time push notifications with PlayFab Matchmaking and PlayFab Lobby.

See also
Lobby and matchmaking
Lobby properties
Owner requirements and privileges
Create a lobby
Lobby ownership changes
Find lobbies
Create searchable lobbies
Getting started with Azure PlayFab Lobby
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

This article describes how to set up the development environment for Azure PlayFab Lobby and start using it.

Prerequisites
You need a PlayFab account to access Lobby and Matchmaking features.
Create/sign in to your PlayFab account. For instructions, see Quickstart: Game Manager.

Download and set up the PlayFab Multiplayer Client SDK


Like the PlayFab Core SDKs, we have Multiplayer SDKs for different platforms and game engines. Select and
download the one that you need.
For download links, see Lobby SDKs.
For Unity and Unreal set up instructions, see the following articles.
Quickstart for Unity
Quickstart for Unreal

Initialize PlayFab Multiplayer Client SDK


Now that you've finished the setup, you're ready to make your first API call and use more Lobby features.
To start making Lobby API calls, you also need the PlayFab Entity Token. Get it via REST calls (GetEntityToken) or
by using the PlayFab Core SDK.

Initialize Lobby
Initialize the PlayFab Multiplayer Client SDK by following these basic steps.
static PFMultiplayerHandle g_pfmHandle = nullptr;
...
...
HRESULT hr = S_OK;

// Initialize the PFMultiplayer library.


hr = PFMultiplayerInitialize(titleId, &g_pfmHandle);
RETURN_IF_FAILED(hr);

// Set an entity token for a local user. The token will be used for operations on behalf of this user.
If using
// the PF Core SDK, this should be called each time the PF Core SDK provides a refreshed token.
hr = PFMultiplayerSetEntityToken(g_pfmHandle, localUserEntity, entityToken);
RETURN_IF_FAILED(hr);

return S_OK;

Next steps
Create a Lobby
Find and join a lobby
Invite another player to a lobby
Use lobby properties to coordinate a game session

See also
Create searchable lobbies
Lobby properties
Lobby Client SDK reference
Lobby SDKs
Create a lobby
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

This article explains how to create a lobby.

How are lobbies created?


There are several ways a lobby can be created.
By your players : Lobbies can be created by players who want get together a team of players to play. These
are client-owned lobbies.
By your game ser vers : Your title's game servers can create lobbies and wait for players to join. These are
server-owned lobbies.
By matchmaking : After a group of players form after matchmaking, a lobby is created as a holding place
before the game starts. These are client-owned lobbies.
From a technical perspective, all lobbies are fall into two main categories based on ownership—server-owned
and client-owned. To learn more, see Owner requirements and privileges.
The general usage of PlayFab Lobby is to temporarily hold a group of players together. For commonly used
applications of Lobby, see Common lobby scenarios.

How lobbies are configured


Several important settings for a lobby are configured during creation: maxMemberCount , accessPolicy ,
owner , and ownerMigrationPolicy .
maxMemberCount defines how many players the lobby can hold
accessPolicy defines who may discover the lobby's connection string
owner defines the lobby's owner which has special permissions to update data on the lobby. This value is
implicitly the client or server entity who is creating the lobby.
ownerMigrationPolicy defines policies for how ownership of the lobby should be transferred if the current
owner leaves the lobby or has trouble maintaining a connection to the lobby.
Additionally, during creation, the lobby creator can also define custom lobby properties and search properties to
append custom data to the lobby session. These custom properties can also be modified over the lifetime of the
lobby by the lobby's owner.
For more information, see Lobby properties.

Example using the Lobby and Matchmaking Client SDK


This example uses the first player in a list of grouped players to create a lobby.
In this code snippet, Lobby properties are passed in as lobbyConfiguration . The first player (client) becomes
the lobby owner. So it's a client-owned lobby. After the lobby is successfully created, it adds other players to the
lobby.

const char* gameModePropertyKey = "GameMode";


auto gameMode = GameMode::Foo;
const char* gameModePropertyValue = EnumToString(gameMode);
const char* playerColorPropertyKey = "PlayerColor";
PlayerColor playerColor = MyGame::GetPlayerColor(m_localUsers[0]);
const char* playerColorPropertyValue = EnumToString(playerColor);

PFLobbyCreateConfiguration lobbyConfiguration{};
lobbyConfiguration.maxMemberCount = 16;
lobbyConfiguration.ownerMigrationPolicy = PFLobbyOwnerMigrationPolicy::Automatic;
lobbyConfiguration.accessPolicy = PFLobbyAccessPolicy::Private;
lobbyConfiguration.lobbyPropertyCount = 1;
lobbyConfiguration.lobbyPropertyKeys = &gameModePropertyKey;
lobbyConfiguration.lobbyPropertyValues = &gameModePropertyValue;

PFLobbyJoinConfiguration creatorMemberConfiguration{};
creatorMemberConfiguration.memberPropertyCount = 1;
creatorMemberConfiguration.memberPropertyKeys = &playerColorPropertyKey;
creatorMemberConfiguration.memberPropertyValues = &playerColorPropertyValue;

// Create a lobby using our first player


PFLobbyHandle lobby;
HRESULT error = PFMultiplayerCreateAndJoinLobby(g_pfmHandle, &m_localUsers[0], &lobbyConfiguration,
&creatorMemberConfiguration, nullptr, &lobby);

See also
Lobby Client SDK reference
Create searchable lobbies
Lobby properties
Lobby and matchmaking
Lobby invites
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

This article provides an overview about Lobby invites and explains how to manage state changes for lobbies
that allow invites.

Invite types
There are two types of invites your game is likely to make use of.
1. In-game invites
2. Platform invites
Joining a lobby by in-game invites
A member of a lobby may invite another player to that lobby directly via the lobby service.
This will share the lobby's connection string with the invited player.
The invited player will receive the invitation via PFLobbyInviteReceivedStateChange and can use the
attached connection string to join the lobby.
These invites work cross-platform but only work in-game.
Joining a lobby by platform invites
Members of the lobby can directly share the lobby's connection string with other players over platform-
specific invite mechanisms.
These invites will not work cross-platform but can be received without the recipient already running the
game.
Once the invited player receives the connection string via the platform mechanism, they can use the attached
connection string to join the lobby.

Client SDK example


Use PFMultiplayerStar tListeningForLobbyInvites on the invite recipient to enable receiving in-game
invites.
The invitation listener will report its status as Listening once it has been successfully setup.
HRESULT AllowInvitations(
const PFEntityKey* entity)
{
return PFMultiplayerStartListeningForLobbyInvites(g_pfmHandle, entity);
}

void HandleInvitationListenerStatusChange(
const PFLobbyInvitationListenerStatusChangedStateChange& invitationListenerStateChange)
{
PFLobbyInvitationListenerStatus status;
HRESULT hr = PFMultiplayerGetLobbyInvitationListenerStatus(
g_pfmHandle,
&invitationListenerStateChange.listeningEntity,
&status);
assert(SUCCEEDED(hr));

switch (status)
{
case PFLobbyInvitationListenerStatus::Listening:
{
Log("%s is listening for invitations", invitationListenerStateChange.listeningEntity.id);
break;
}
case PFLobbyInvitationListenerStatus::NotAuthorized:
{
Log("Invitation listener not authorized!"); // this is likely an issue with the listener's
entity token.
break;
}
default:
}
}

Use PFLobbySendInvite to send an invite to another PlayFab user via the lobby service.
The recipient will receive a PFLobbyInviteReceivedStateChange .

HRESULT SendInvite(PFLobbyHandle lobby, const PFEntityKey* sender, const PFEntityKey* receiver)


{
return PFLobbySendInvite(lobby, sender, receiver, nullptr);
}

void HandleInvitationNotification(const PFLobbyInviteReceivedStateChange& invite)


{
Log("%s invited to lobby by %s", invite.listeningEntity.id, invite.invitingEntity.id);
// pass invite.connectionString to PFMultiplayerJoinLobby
}

See also
Lobby and matchmaking
Find lobbies
Join lobbies
Lobby properties
Joining lobbies and connection strings
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

Players join lobbies by providing the lobby service with a lobby's "connection string", an opaque identifier which
grants membership to the lobby.
Players can discover connection strings and join lobbies in the following ways.
1. By using in-game invites—A member of a lobby may invite another player to that lobby directly via the lobby
service. This will share the lobby's connection string with the invited player. These invites work cross-
platform but only work in-game. For more information, see Lobby invites
2. By using platform-provided invites—Members of the lobby can directly share the lobby's connection string
with other players over platform-specific invite mechanisms. These invites will not work cross-platform but
can be received without the recipient already running the game.
3. By searching for available lobbies with FindLobbies and joining an available lobby
4. By sharing the lobby's connection string via any out-of-band, custom discovery mechanism

Connection strings and Lobby IDs


Aside from connection strings, lobbies have another identifer known as LobbyId . LobbyId is the unique
identifier for a lobby. Titles may use LobbyId to distinguish between multiple lobbies that a player is in, but
LobbyIds cannot be used to join the lobbies or directly query them for any information which requires
membership. Therefore, your title doesn't have to keep LobbyId a secret. Connection strings, on the other hand,
grant access to lobbies so care should be taken to keep from exposing them to unwanted, outside parties.

Client SDK example


Here's a brief snippet which demonstrates passing a connection string to the PFMultiplayerJoinLobby API
provided by the Client SDK.
In this snippet, the connection string could be provided by any of the discovery mechanisms mentioned above:
in-game invites, platform-specific invites, or filtered lobby searches.
//
// Set some initial member properties for the newly joining member
//
const char* playerColorPropertyKey = "PlayerColor";
const char* playerColorPropertyValue = MyGame::GetPlayerColorString(localUser);

PFLobbyJoinConfiguration joinConfig;
joinConfig.memberPropertyCount = 1;
joinConfig.memberPropertyKeys = &playerColorPropertyKey;
joinConfig.memberPropertyValues = &playerColorPropertyValue;

//
// Join the lobby using the connection string
//
HRESULT hr = PFMultiplayerJoinLobby(
g_pfmHandle,
&localUser,
connectionString,
&joinConfig,
nullptr,
nullptr);

See also
Find lobbies
Create searchable lobbies
Lobby and matchmaking
Lobby properties
Create a lobby
Lobby properties
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

This article describes custom properties stored on the lobby. Use this functionality to store metadata about the
game sessions that your lobby's represent.

Pre-defined properties
Each lobby has a set of pre-defined properties commonly needed for most game scenarios.

P RO P ERT Y DEF IN IT IO N

lobbyId This is the unique identifier for a lobby. It can be used to


distinguish between multiple lobbies that a player may be a
part of.

connectionString The identifier used to join the lobby. It is provided by the


Lobby service. When an invite is sent to other players, the
connectionString is sent as the invitation.

maxMemberCount The maximum number of players allowed in the lobby. This


property can only be changed by owner.

owner The entity that owns the lobby. Some lobbies may
temporarily be ownerless in some circumstances. To learn
more, see Ownership changes.

ownerMigrationPolicy Policy determines how a new owner will be chosen. To learn


more, see Ownership changes.

accessPolicy Policy indicates who can discover the lobby's connection


string. This property can only be changed by the owner.

membershipLock This value indicates whether new members may join the
lobby or not. When Locked , new members may not join.
When Unlocked new members may join. This property can
only be changed by the owner.

Custom Properties
There are 3 types of custom properties that titles can define.
1. Custom lobby properties
These properties apply to the whole lobby.
Only members of the lobby can see these properties.
Only the owner of the lobby can change these properties.
2. Custom member properties
There is a unique map of member properties for each member in the lobby
Only members of the lobby can see these properties.
All members of the lobby can see every other members' properties.
Each member may modify their own member properties but cannot modify another member's
properties.
Once a member leaves the lobby, their member properties are deleted from the lobby.
3. Custom search properties.
These are special properties which can be used by all players in your title to search for lobbies
matching a specific criteria.
These properties apply to the whole lobby.
Only the owner of the lobby can change these properties.
There are restrictions on what keys you can use for these properties.
To learn more, see Create searchable lobbies.
All properties are maps of key-value pairs.

See also
Create a lobby
Owner requirements and privileges
Lobby and matchmaking
Find lobbies
Create searchable lobbies
Create searchable lobbies
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

This article explains how to create lobbies that are searchable.


To make a lobby searchable, its access policy must either be Public or Friends . Lobbies with a Private access
policy will not be joinable from search queries and must be joined via invites. It's common to configure this
access policy when initially creating the lobby.
Once a lobby's access policy is set correctly, other players can search for it using Find lobbies.
Additionally, the owner of the lobby may define custom search properties which other players can use when
searching for lobbies to find more specific results.
To learn more, see Find lobbies and Join lobbies.

Example code
In this example, the lobby created has the following custom search properties defined.
Game mode = "DeathMatch"
Competition style = "Ranked"
Skill level = Skill level of the person who created the lobby
static PFMultiplayerHandle g_pfmHandle; // initialized elsewhere

#define PFLOBBY_SEARCH_KEY_GAME_MODE "string_key1"


#define PFLOBBY_SEARCH_KEY_COMPETITION_STYLE "string_key2"
#define PFLOBBY_SEARCH_KEY_SKILL "number_key1"

#define GAME_MODE_DEATH_MATCH "DeathMatch"


#define COMPETITION_STYLE_RANKED "Ranked"

PFEntityKey m_localUser;
namespace MyGame {
uint32_t GetPlayerSkill(); // defined elsewhere
}

void CreateLobbyWithSearchProperties()
{
std::string playerSkill = std::to_string(MyGame::GetPlayerSkill());

const char* searchPropertyKeys[] = {


PFLOBBY_SEARCH_KEY_GAME_MODE,
PFLOBBY_SEARCH_KEY_COMPETITION_STYLE,
PFLOBBY_SEARCH_KEY_SKILL,
};

const char* searchPropertyValues[_countof(searchPropertyKeys)] = {


GAME_MODE_DEATH_MATCH,
COMPETITION_STYLE_RANKED,
playerSkill.c_str(),
};

PFLobbyCreateConfiguration lobbyConfiguration{};
lobbyConfiguration.maxMemberCount = 16;
lobbyConfiguration.searchPropertyCount = _countof(searchPropertyKeys);
lobbyConfiguration.searchPropertyKeys = searchPropertyKeys;
lobbyConfiguration.searchPropertyValues = searchPropertyValues;

PFLobbyHandle lobby;
HRESULT hr = PFMultiplayerCreateAndJoinLobby(
g_pfmHandle,
&m_localUser,
&lobbyConfiguration,
nullptr,
nullptr,
&lobby);
}

See also
Find lobbies
Lobby properties
Owner requirements and privileges
Create a lobby
Find lobbies
5/24/2022 • 4 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

It's often useful for titles to let players find lobbies that meet a particular set of criteria like map and difficulty
level among other in-game qualities. This enables players to find the game sessions they want with the people
they want.
This article explains how to use FindLobbies to enable players to find lobbies. To see how to find lobbies can be
used in game titles, see Common Scenarios.

Understanding the relationship between lobby search properties and


finding lobbies
Players make their lobbies discoverable by defining search properties. Players find these discoverable lobbies by
calling FindLobbies with query strings to filter and sort their search results based on the search properties
defined across the currently active lobbies. Lobbies which match these queries will be returned to the calling
player.
For more information on defining search properties, checkout Creating searchable lobbies

How to use FindLobbies


When calling FindLobbies you can use the filter parameter to restrict your search results to only those
matching some set of criteria based on the lobby's custom search properties.
Additionally, you can use the sorting parameter to sort the results you get back from the service based on the
search properties. This is useful since the service will only return a limited number of search results. Sorting
ensures you see the most relevant search results.
Common Scenarios
Here are a few common ways the FindLobbies functionality is used in titles.
Finding lobbies for game sessions for a specific game mode in your title
Finding lobbies for game sessions your friends are hosting
Finding lobbies for game sessions with enough players for all local players
Supported search keys
Only a restricted set of keys are allowed to be used when defining custom search properties.
For string properties, the following keys are supported: string_key1, string_key2, [...] string_key30
For numeric properties, the following keys are supported: number_key1, number_key2, [...] number_key30
Constructing query strings for FindLobbies
Query strings for the FindLobbies APIs are structured in an OData-like syntax.
These OData operators can be used to compose query strings
O P ERATO RS M EA N IN G EXA M P L E

eq Equal to string_key1 eq 'CaptureTheFlag'

lt less than number_key2 lt 10

le less than or equal to number_key2 le 10

gt greater than number_key3 gt 100

ge greater than or equal to number_key3 ge 100

and AND string_key1 eq 'CaptureTheFlag' AND


number_key2 lt 10

not NOT not string_key1 eq 'CaptureTheFlag'

NOTE : When comparing string properties, be sure to wrap the compared value in single quotes. e.g.
"string_key1 eq 'SOME STRING VALUE' ". Numeric properties do not require this.

Example Lobby and Matchmaking Client SDK code


In this example, the player wants to find all lobbies with the following search parameters.
Game mode == "DeathMatch"
Competition style != "Ranked"
Player skill > Min skill
Player skill < Max skill
Then sort the results using the following parameters.
Sort by the distance from optimal skill where closer skill levels sort higher.
Then sort by number of current members in the lobby where lower member counts sort higher.

static PFMultiplayerHandle g_pfmHandle = nullptr;

#define SUPPORT_XBL_CROSSPLAY

#define PFLOBBY_SEARCH_KEY_GAME_MODE "string_key1"


#define PFLOBBY_SEARCH_KEY_COMPETITION_STYLE "string_key2"
#define PFLOBBY_SEARCH_KEY_SKILL "number_key1"

#define GAME_MODE_DEATH_MATCH "DeathMatch"


#define COMPETITION_STYLE_RANKED "Ranked"

// Find lobbies based on player's search criteria.


void FindGamesWithRuntimeQuery(
uint32_t minimumSkill,
uint32_t maximumSkill,
uint32_t optimalSkill)
{
PFLobbySearchFriendsFilter friendsFilter;
friendsFilter.includeSteamFriends = true;
#ifdef SUPPORT_XBL_CROSSPLAY
friendsFilter.includeXboxFriendsToken = MyGame::GetLocalUserXboxToken();
#endif // SUPPORT_XBL_CROSSPLAY

// Limit results based on friend's filter.


PFLobbySearchConfiguration searchConfiguration = { 0 };
searchConfiguration.friendsFilter = &friendsFilter;

// Create filter string based on player's search parameters.


std::string filterString;
filterString += PFLOBBY_SEARCH_KEY_GAME_MODE + std::string(" eq ") + GAME_MODE_DEATH_MATCH;
filterString += " and not";
filterString += PFLOBBY_SEARCH_KEY_COMPETITION_STYLE + std::string(" eq ") + COMPETITION_STYLE_RANKED;
filterString += " and ";
filterString += PFLOBBY_SEARCH_KEY_SKILL + std::string(" -ge ") + std::to_string(minimumSkill);
filterString += " and ";
filterString += PFLOBBY_SEARCH_KEY_SKILL + std::string(" -le ") + std::to_string(maximumSkill);

// Create sort string based on player's sort preference.


std::string sortString;
sortString += std::string("distance{") + PFLOBBY_SEARCH_KEY_SKILL + "=" + std::to_string(optimalSkill) +
"} asc";
sortString += "," + std::string(c_lobbyMemberCountSearchKey) + " asc";

searchConfiguration.filterString = filterString.c_str();
searchConfiguration.sortString = sortString.c_str();

HRESULT hr = PFMultiplayerFindLobbies(g_pfmHandle, &m_localUser, &searchConfiguration, nullptr);


}

void ProcessStateChanges()
{
while (true)
{
uint32_t stateChangeCount;
const PFLobbyStateChange* const* stateChanges;
RETURN_VOID_IF_FAILED(PFMultiplayerStartProcessingLobbyStateChanges(
g_pfmHandle,
&stateChangeCount,
&stateChanges));

for (uint32_t i = 0; i < stateChangeCount; ++i)


{
const PFLobbyStateChange* stateChange = stateChanges[i];
switch (stateChange->stateChangeType)
{
case PFLobbyStateChangeType::FindLobbiesCompleted:
{
GuiPostCurrentLobbySearchResults(
static_cast<const PFLobbyFindLobbiesCompletedStateChange&>(*stateChange));
break;
}
default:
{
break;
}
}
}

RETURN_VOID_IF_FAILED(PFMultiplayerFinishProcessingLobbyStateChanges(
g_pfmHandle,
stateChangeCount,
stateChanges));
}
}

// Update game UI to display search results when a list of matching lobbies is returned.
void GuiPostCurrentLobbySearchResults(
const PFLobbyFindLobbiesCompletedStateChange& stateChange)
{
if (FAILED(stateChange.result))
{
GuiToastErrorAndExitScreen();
return;
}
for (uint32_t i = 0; i < stateChange.searchResultCount; ++i)
{
const PFLobbySearchResult& searchResult = stateChange.searchResults[i];
GuiPostLobbySearchResultRow(searchResult); // defined elsewhere
}
}

See also
Create searchable lobbies
Join lobbies
Lobby and matchmaking
Lobby properties
Create a lobby
Owner requirements and privileges
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

This article explains about Lobby owner requirements and privileges.

Owner requirements
The owner of a lobby can be either a client or a server. Both must have access to the title. Client owners must
also be a member of the lobby.
In other words, there are two main types of lobbies available—Server-owned and client-owned.
Server-owned lobbies can be lobbies owned by your title and waits for players to join. These lobbies have your
title game server listed as the owner. Client-owned lobbies are those that are created on behalf on players. These
lobbies have a client listed as the owner. It's important to note that PlayFab Lobby is a service so all lobbies are
created on PlayFab servers.
To learn how to create lobbies, see Create a lobby and Lobby and matchmaking walkthrough.

Privileges
The owner of a lobby has special privileges.
1. The owner can set lobby level items.
Server owners are allowed to modify everything that can be modified, except member data.
Client owners are allowed to modify everything a server owner can and their own member data. They
can't modify other members' data.
2. The owner can remove members from the lobby.
3. The owner may appoint another owner. This occurs by sending an update with the owner field specified.
The server owner can only specify another server to be the new owner.
The client owner can only specify another client, who is a member of the lobby, to be the new owner.
Privileges for server owners only
Server owner can query for lobbies they own.
Lobby is hidden during ownership migration. After a lobby owner change, the new server owner needs to re-
establish notification subscription and get a new subscribe connection. This turns the lobby visibility back on
for search.
Server owner can control notifications to its members

See also
Lobby properties
Create a lobby
Lobby ownership changes
Ownership changes
5/24/2022 • 3 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

Most game scenarios benefit from having a specially selected "owner" of the lobby. So it's important to define
policies to determine how ownership of the lobby migrates when the owner of the lobby leaves or is
disconnected.

Ownership migration policies


The PlayFab Lobby service provides a set of pre-defined ownership migration policies to define who should
become the new owner of the lobby if the current owner leaves or is disconnected.
The table below describes how each ownerMigrationPolicy functions.

O W N ER O W N ERM IGRAT IO N P O L IC Y DESC RIP T IO N

Client Automatic The Lobby service will automatically


assign another connected owner when
the current owner leaves or
disconnects. Non-owner members
cannot re-assign the owner.

Client Manual The Lobby service will clear the owner


field when the current owner leaves.
While the owner is connected, non-
owner members cannot re-assign the
owner. If the owner has disconnected,
any member may set themselves as
the current owner.

Client None The Lobby service will clear the owner


field when the current owner leaves.
The owner field will be unaffected if the
current owner disconnects. Any
member, including non-members can
re-assign the owner at anytime.

Server Server Any server can set themselves as


owner. Your title must decide which
server should become the new owner.
If the server-owner disconnects, the
lobby is temporarily hidden from
search. Lobby does not enforce
protection or additional abilities from
one server to another.

Proactive ownership changes


Some game scenarios may require ownership to proactively transfer from the current owner to a new owner.
The table below describes how proactive ownership changes are affected by the current
ownerMigrationPolicy .

O W N ER O W N ERM IGRAT IO N P O L IC Y DESC RIP T IO N

Client Automatic The current owner may promote


another member as owner in their
place.

Client Manual The current owner may promote


another member as owner in their
place. If there is no owner or the
owner has disconnected, any member
can promote themselves to be the new
owner.

Client None The current owner can promote any


other member as owner. Any member
can promote themselves to be the new
owner even if the current owner is still
present and connected.

Server Server Any server can promote themselves to


owner. Proactive server ownership
migration may be useful to handle
game server migration.

Extra guidance for server owners


Any server authorized for the title may take over the ownership of any lobby authorized for that title. The
Lobby service does not protect ownership between game servers for the same title.
Server-owned lobbies are hidden when the server-owner is disconnected.
Game servers can query for lobbies they own.

Frequently asked questions


When will the owner field be cleared?
The owner field will be cleared when the current owner leaves the lobby and the owner migration policy is
unable to select a new owner. Automatic migration policy is the only policy that will try to automatically select
a new owner.
NOTE : The owner will not be cleared when the owner disconnects and a new owner can't be automatically
selected. This is intentional to be robust to service outages.
What happens when the last member leaves the lobby?
For client-owned lobby, the lobby is always deleted when the last member leaves.
For server-owned lobby, no action is taken.
What's the difference between Manual and None owner migration policy?
Manual ownership migration policy allows your title to manually manage ownership but still provide
ownership protection. The None policy provides your title full ownership control without any assistance or
protection from the service.

See also
Lobby properties
Owner requirements and privileges
Create searchable lobbies
Create a lobby
Use Lobby and Matchmaking Together
5/24/2022 • 5 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

When designing multiplayer games, matchmaking and lobbies are often used together to help people form
groups to play together.
PlayFab Lobby and PlayFab Matchmaking helps you implement a wide variety of multiplayer scenarios.
This article describes the relationship between these two services and illustrates how they can be used together
to implement a game scenario specified below.

Understand the relationship between Lobby and Matchmaking


Lobby and Matchmaking work seamlessly together to create cohesive multiplayer matchmaking experience for
your title.
Matchmaking gathers a set of players together looking to participate in a game session.
After matchmaking has identified a set of players, Lobby provides them a communication medium to
coordinate joining a game session together.
Common scenarios for lobby include sharing game server connection information, sharing client IPs
for peer-to-peer games, and sharing player configurations.
Arranged lobbies
Titles can use "Arranged Lobbies" to support easily creating lobbies for your players which have been grouped
together via matchmaking.
After the matchmaking ticket has successfully matched a group of players, the matchmaking ticket will contain a
lobbyArrangementString . Each player can then pass the arrangement string to
PFMultiplayerJoinArrangedLobby to join the same lobby.

Example Scenario
A player wants to play with other people. The player starts a multiplayer game, invites friends, and waits for
others to join.
Design specifications
The game is open for everyone to join.
The initial set of players is populated via matchmaking.
The lobby owner is able to invite friends to join.
When the required number of players are met, all players in the lobby receive a message asking if they're
ready to start the game. They have one minute to respond. The game starts after all the players confirmed
that they're ready to start game.
If players in the lobby did not confirm their ready-to-play status, the lobby owner can remove them as
inactive players and use matchmaking to find new players to quickly replace them.
When any player gets disconnected unexpectedly during the game, the title should find a new replacement
for the dropped player through matchmaking using server backfill.
When the game ends, all players return to the lobby. Players are awarded team achievements equally. They
have the option to either stay to start another game together or leave the lobby.
Implementation
This section describes how to use Matchmaking and Lobby to implement the above design specifications.
Create a matchmade lobby
Send invites to friends
Allow people to find and join game
Notify players to start game
Remove and replace inactive players
Handle a finished game
Create a matchmade lobby
Create a public lobby for a group of matchmade players.
Each player creates a matchmaking ticket with their specified matchmaking attributes.
To learn more, see Specify ticket attributes.
All created tickets are added to a matchmaking queue be matched with one another.
Tickets are matched based on rules.
Rules can be defined in the matchmaking queue configuration.
To learn more, see Configure matchmaking queues.
After matchmaking, each player joins the matchmade lobby via the matchmaking ticket's
lobbyArrangementString .
When joining the arranged lobby, specify that the lobby's accessPolicy is Public to make the lobby
open.
See Arranged lobbies for more information.
The first player to join the arranged lobby becomes the owner for the lobby.
The lobby properties can be used to specify which game map a game session intends to use.
For more information, see Lobby properties.
Use search properties to enable players to find this lobby and game session among all of the active lobbies
in your title.
For more information, see Search properties.
Send invites to friends
Allow the lobby owner to select friends and send invites.
Get lobby owner's friends list
Display game UI to allow lobby owner to select friends to invite
Send in-game invites to selected friends.
For more information, see Lobby invites.
Allow people to find and join game
Setup the lobby's search properties to allow other players to find it
Display all lobbies in your game UI. Your title should also provide a way to accept player's search terms.
Use PFMultiplayerFindLobbies using the player's search parameters to return a list of lobbies that match
the criteria.
After a player selects to join a game, use PFMultiplayerJoinLobby to add the player to the game.
Notify players to start game
Inform all players in the lobby that game is ready to start
When the required number of players are in the lobby, display game UI to get players to confirm that they're
ready to start play.
Allow the lobby owner to view these confirmation responses.
Remove and replace inactive players
Lobby owner has the ability to remove inactive or disconnected players and initiate matchmaking to fill up the
remaining spots
If a player has discoonected or did not respond within the given set duration (one minute), use
PFLobbyForceRemoveMember to remove the player.
The lobby owner will use CreateSer verBackfillTicket to create a matchmaking ticket. Tickets created using
this API are given priority during searching. This is to minimize gameplay disruption. To learn more, see
Using server backfill tickets.
After joining the backfill lobby, the game's lobby owner can share the original lobby's connection string with
the new backfill players and they can join the original lobby.
Extend the game start time when appropriate.
Handle a finished game
After the game has finished, all players return to the lobby screen to complete the game session.
Lobbies are transient so any data from the lobby which should be persisted should be retained by each
player at this point.
For example, some game scenarios may benefit from processing data stored in the member
properties and turning that data into player achievements.
Players who want to continue playing with the same group will stay in the lobby.
Players who want to stop playing with the same group will leave the lobby with PFLobbyLeave and restart
the process with a new matchmaking group.

See also
Create a lobby
Lobby invites
Search properties
Lobby properties
Using server backfill tickets in Matchmaking
Lobby and Matchmaking real-time notifications
5/24/2022 • 2 minutes to read • Edit Online

Overview
The Matchmaking and Lobby features have built in support for real-time notifications. Notifying players of
changes to Matchmaking or Lobby has never been easier, as the work to handle notifications is done for you.
New APIs will allow connected clients to subscribe for notifications of Lobby and Matchmaking changes. With
this addition, you'll no longer need to poll for changes to matches or lobbies.
The client SDK has been designed to simplify your work. The client SDK manages calls between clients and
Lobby and Matchmaking services. It handles the delivery of notifications from those services to connected
clients in real time. Real-time notifications have cross-platform support, and will work anywhere PlayFab
supplies a client SDK. Matchmaking and Lobby can be used separately or together, and real-time notifications
will work in either case. There's no support for real-time notifications without the client SDK at this time. Real-
time notifications aren't available as a solution for stand-alone or general use.

How do real-time notifications work


Each client maintains a single WebSocket to receive real-time notifications. When there are updates to
Matchmaking or Lobby resources in the cloud, the client SDK will forward notifications in real-time to all
connected clients subscribed to those resources.
When a client connects to receive real-time notifications, they'll open a new WebSocket connection to receive
notifications and listen for change events. When a client creates a lobby, joins a lobby, starts listening for
invitations, or creates a Matchmaking ticket, the connected client will subscribe to a Lobby or Matchmaking
resource to listen for changes. The client will be notified when there's an update on the resource topic they’ve
subscribed to. For example, if a client has subscribed to a Lobby resource, they may be notified on change
events like Player A or B has joined or left a Lobby. Matchmaking and Lobby documentation describe in more
detail the operations that will power notifications.
The WebSocket connection that enables real-time notifications is also used for detecting client connectivity. This
client connectivity status is used by the Lobby service to power lobby ownership management.

Shared connection support


Matchmaking and Lobby notifications have support to share a single WebSocket connection, which may be
useful if you’re creating a title with couch co-op. Today, up to eight local users may share the WebSocket
connection, and local players can be added or removed to that shared connection. Multiple users sharing the
same connection can subscribe to topics to get notifications for Matchmaking or Lobby events for those topics.

Using the client SDK


The client SDK simplifies your work for cross-network and cross-platform play by handling real-time
notifications for you. Notifications are sent to clients on receiving invites, joining and updating lobbies, finding
matches, and more. The client SDK enables cross-platform play and real-time notifications on any platform that
PlayFab offers SDK support. Sending notifications to clients is automatic, and the developer doesn't have to do
any work to enable notifications.
PFMultiplayer C/C++ API overview - PFLobby.h
5/24/2022 • 3 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

Functions
F UN C T IO N DESC RIP T IO N

PFLobbyAddMember Add a local user as a member to the lobby.

PFLobbyForceRemoveMember Forcibly remove an entity from the lobby.

PFLobbyGetAccessPolicy Gets the access policy of the lobby.

PFLobbyGetConnectionString Gets the default connection string associated with the lobby.

PFLobbyGetCustomContext Retrieves the app's private, custom pointer-sized context


value previously associated with this lobby object.

PFLobbyGetLobbyId Gets the ID of the Lobby.

PFLobbyGetLobbyProperty Get the lobby property value from its key.

PFLobbyGetLobbyPropertyKeys Get the list of lobby property keys.

PFLobbyGetMaxMemberCount Gets the max member count of the lobby.

PFLobbyGetMemberProperty Get the member property's value from its key.

PFLobbyGetMemberPropertyKeys Get a list of the specified member's property keys.

PFLobbyGetMembers Gets the list of PlayFab entities currently joined to the lobby
as members.

PFLobbyGetMembershipLock Gets the lobby's current membership lock state.

PFLobbyGetOwner Gets the current owner of the lobby.

PFLobbyGetOwnerMigrationPolicy Gets the owner migration policy of the lobby.

PFLobbyGetSearchProperty Get the search property value from its key.

PFLobbyGetSearchPropertyKeys Get the list of search property keys.


F UN C T IO N DESC RIP T IO N

PFLobbyLeave Request one or all local users to leave the lobby.

PFLobbyPostUpdate Post an update to the lobby.

PFLobbySendInvite Send an invite to this lobby from the local user to the invited
entity.

PFLobbySetCustomContext Configures an optional, custom pointer-sized context value


with this lobby object.

PFMultiplayerCreateAndJoinLobby Create a new lobby and add the creating PlayFab entity to it.

PFMultiplayerFindLobbies Search for lobbies on behalf of the local user.

PFMultiplayerFinishProcessingLobbyStateChanges Returns an array of PFLobbyStateChanges that were being


processed.

PFMultiplayerGetLobbyInviteListenerStatus Retrieve the status of the entity's invite listener.

PFMultiplayerJoinArrangedLobby Joins a lobby using an arrangement string provided by


another service, such as matchmaking. If no one has joined
the lobby yet, the lobby is initialized using the configuration
parameters.

PFMultiplayerJoinLobby Join a lobby as the local PlayFab entity.

PFMultiplayerStartListeningForLobbyInvites Enables the Lobby invite listener for a given entity.

PFMultiplayerStartProcessingLobbyStateChanges Retrieves an array of all PFLobbyStateChanges to process


since the last such call.

PFMultiplayerStopListeningForLobbyInvites Disables the Lobby invite listener for a given entity.

Structures
ST RUC T URE DESC RIP T IO N

PFLobbyArrangedJoinConfiguration The initial configuration data used when joining an arranged


lobby.

PFLobbyCreateConfiguration The initial configuration data used when creating a lobby.

PFLobbyDataUpdate A request to make an update to the shared portion of the


lobby on behalf of a member.

PFLobbyJoinConfiguration The initial configuration data used when joining a lobby.

PFLobbyMemberDataUpdate A request to make an update to the member-owned portion


of the lobby document.
ST RUC T URE DESC RIP T IO N

PFLobbyMemberUpdateSummary A collection of hints about an update which has been


successfully applied to the lobby on behalf of a member.

PFLobbySearchConfiguration The configuration structure used to specify how a


PFMultiplayerFindLobbies operation should be performed.

PFLobbySearchFriendsFilter The filter structure used to limit lobby search results to only
those lobbies owned by the player's friends.

PFLobbySearchResult An entry in the collection of lobby search results received


upon successful completion of a PFMultiplayerFindLobbies
operation.

State changes
STAT E C H A N GE DESC RIP T IO N

PFLobbyAddMemberCompletedStateChange Information specific to the AddMemberCompleted type of


state change.

PFLobbyCreateAndJoinLobbyCompletedStateChange Information specific to the CreateAndJoinLobbyCompleted


type of state change.

PFLobbyDisconnectedStateChange Information specific to the Disconnected type of state


change.

PFLobbyDisconnectingStateChange Information specific to the Disconnecting type of state


change.

PFLobbyFindLobbiesCompletedStateChange Information specific to the FindLobbiesCompleted type of


state change.

PFLobbyForceRemoveMemberCompletedStateChange Information specific to the ForceRemoveMemberCompleted


type of state change.

PFLobbyInviteListenerStatusChangedStateChange Information specific to the InviteListenerStatusChanged type


of state change.

PFLobbyInviteReceivedStateChange Information specific to the InviteReceived type of state


change.

PFLobbyJoinArrangedLobbyCompletedStateChange Information specific to the JoinArrangedLobbyCompleted


type of state change.

PFLobbyJoinLobbyCompletedStateChange Information specific to the JoinLobbyCompleted type of


state change.

PFLobbyLeaveLobbyCompletedStateChange Information specific to the LeaveLobbyCompleted type of


state change.

PFLobbyMemberAddedStateChange Information specific to the MemberAdded type of state


change.
STAT E C H A N GE DESC RIP T IO N

PFLobbyMemberRemovedStateChange Information specific to the MemberRemoved type of state


change.

PFLobbyPostUpdateCompletedStateChange Information specific to the PostUpdateCompleted type of


state change.

PFLobbySendInviteCompletedStateChange Information specific to the SendInviteCompleted type of


state change.

PFLobbyStateChange A generic, base structure representation of an event or


change in state.

PFLobbyUpdatedStateChange Information specific to the Updated type of state change.

Enumerations
EN UM ERAT IO N DESC RIP T IO N

PFLobbyAccessPolicy Values representing the lobby's access policy.

PFLobbyDisconnectingReason Reasons the client no longer has access to the Lobby.

PFLobbyInviteListenerStatus Values representing the current status of an invite listener.

PFLobbyMemberRemovedReason Reasons why a member was removed from a lobby.

PFLobbyMembershipLock Values representing the state of the lobby's membership


lock.

PFLobbyOwnerMigrationPolicy The available policies the lobby service can use to migrate
lobby ownership between members.

PFLobbyStateChangeType The types of state changes that can occur.


PlayFab Multiplayer C++ SDK release notes
5/24/2022 • 2 minutes to read • Edit Online

1.1.1
April 13, 2022
Bug fixes
Switch: Provides a new PAL header required to build against PlayFab Multiplayer.

1.1.0
March 4, 2022
API changes
PFMultiplayerGetErrorMessage's API signature has changed. Previously this function returned an HRESULT
and used an output paramter to return the error message string. Now the function returns the string directly.
New features
GDK: Added support for automatically handling suspend and resume on Xbox.
Bug fixes
Fixed a bug where using initial member data passed to PFMultiplayerJoinLobby would be ignored if the
player was rejoining a lobby.

1.0.0
November 23, 2021
PlayFab Multiplayer is now available in private preview. For an overview of Matchmaking and Lobby features,
check out:
PlayFab Lobby Overview
PlayFab Multiplayer Lobby Quickstart
PlayFab Matchmaking Overview
PlayFab Multiplayer Matchmaking Quickstart
Azure PlayFab Party overview
5/24/2022 • 2 minutes to read • Edit Online

Azure PlayFab Party is a low-latency chat and data communication solution for cross-platform and cross-device
multiplayer games. The voice and text features in Party can be used as a standalone chat solution.
For multiplayer games that use a server-client authoritative architecture to curtail competitive cheating concerns
or support devices with limited resources, consider multiplayer servers like PlayFab multiplayer servers to host
custom, dedicated game logic in a dynamically scaling cloud environment and use Party for chat
communication.
This topic provides a high-level overview of Party features. For details, see Party features.

Features
Party is designed for use on many platforms like Android, iOS, Nintendo Switch, Google Stadia, PlayStation, PC,
and Xbox. Party also provides C/C++ SDKs and SDKs for use with game engines like Unity and Unreal. For a
complete list, see Party SDKs.
Interoperable multiplayer infrastructure
Cross-network/cross-platform multiplayer game experiences.
Low-latency secure data communication
Industry-standard encryption and authentication.
Cross-platform mesh: automatic low-latency cloud relay or select regions yourself, choosing from
Azure regions distributed across the globe
Direct peer-to-peer functionality.
Background Quality of Service (QoS) measurements.
Flexible topology design possibilities
Everyone-to-everyone.
Constrained to "teams" or game-defined "channels" and more.
Accessible voice and text chat
Real-time speech-to-text and text-to-speech.
Real-time translation for text and voice by using Azure Cognitive Services.
Ability to add real-time custom voice effects like spatial sound.
Capabilities designed for multiplayer games
Efficient game states and logic delivery.
Integrates with custom discovery systems—players finding other players.
Policy enforcement for connectivity and communication.
Party is a managed game service. Discounts are available when you use Party with Xbox Live. For pricing
information, see PlayFab pricing. To learn about the meters that drive billing, see Party pricing.
If you are interested, here is a video of our presentation at Microsoft Game Dev 2021. The presentation explains
the above Party features in greater detail with demos and includes a quickstart tutorial.

See also
Party features
Getting started with Party
Multiplayer servers
Multiplayer
Matchmaking
Party and direct peer-to-peer connections
Azure PlayFab Party features
5/24/2022 • 5 minutes to read • Edit Online

This topic provides details about Azure PlayFab Party features and how you can use them in your game.
For a high-level summary of Party features, see Party overview. If you're ready to start developing, see Getting
started with Party.

Interoperable multiplayer infrastructure


Our goal is to enable you to build interoperable multiplayer experiences across devices and platforms when
you're using Party and other PlayFab multiplayer services.
When you're implementing cross-play, always adhere to the best industry design practices. This helps ensure
that your game's multiplayer experiences don't put certain device form factors at a disadvantage relative to
other devices. Remember to verify that your cross-network/cross-platform multiplayer and player activity
design complies with all applicable platform policies. This means checking with every platform that your game
is on.

NOTE
You're responsible for the compliance of your multiplayer and cross-network implementation.

Low-latency secure data communication


Industry-standard encryption and authentication
Party uses industry-standard encryption and authentication for all communication (management data, game
data, and real-time communication). This includes all peer-to-peer transmissions and all transactions to Azure
services, whether they're web services (using HTTPS) or our transparent cloud relay service (which uses DTLS).
Cross-platform mesh
Party enables data communication by automatically connecting players through a transparent, low-latency
cloud relay or select regions on your own, choosing from one of our Azure regions that are distributed across
the globe. Alternatively, you can use actual direct peer-to-peer connectivity capabilities.
You can make use of our background Quality of Service (QoS) measurements to ensure that you have the best
possible data connection for communication. For more information, see Party QoS measurements.
Networking transport capabilities
Our networking capabilities expand on User Datagram Protocol (UDP) features to provide datagram transport
capabilities, including guaranteed delivery, sequential delivery, and coalescing, that are ideal for real-time
multiplayer games. For more information, see Transport options.

Flexible topology design possibilities


The flexible design of Party supports a variety of communication topologies. You can create a mesh that suits
your game.
You can enable chat at any time or send data messages in the following patterns.
Everyone-to-everyone
Unidirectionally from one-to-many
Constrained to "teams" or game-defined "channels"
Multiple local players on a single device
Connecting to more than one distinct group of players at a time
Arbitrary symmetric or asymmetric subsets, or combinations of the previously mentioned patterns
Party objects in multiple networks can support devices that connect to more than one network at a time. An
example usage is to maintain communication with a set of friends over time. This group of friends is still able to
join and leave larger, separate game sessions with strangers.
To learn more about designing networks, see Party objects and their relationships.

Accessible voice and text chat


Party chat offers the following communication functionalities.
Voice chat: Player devices can bind audio devices to Party networks to accomplish real-time voice chat.
Text chat: Players are able to send text chat messages to one another. In-game chat text messages, even
when text-to-text translation or text-to-speech synthesis is activated, don't drive metering and aren't billed
to your account.
Speech-to-text: Player voice and synthesized text-to-speech voice can be transcribed into text
messages. This functionality was originally designed to enable games to be accessible. It's also useful
when gaming in a noisy environment.
Text-to-speech/voice synthesis: Generate audio from text. It can be used to synthesize player voice to
read incoming text to the recipient. Like speech-to-text, it can be used for making your game more
accessible.
Ability to add real-time custom voice effects: Access to data in audio buffer enables you to add
real-time custom effects like spatial sound using external sound engines. For more information, see Using
real-time audio manipulation to apply custom voice effects
Real-time translation: Incoming speech and text can be translated in real-time.
Incoming speech can be translated into more than 60 languages. Your input source is voice. The
output target is audio or text in a different language. For the latest information, see Azure Cognitive
Speech Translation.
Incoming text can be translated into more than 70 languages. Your input source is text. The output
target is text or audio in a different language. For the latest information, see Azure Cognitive
Translator.
Text moderation: Text chat can be moderated in real-time to filter out offensive language. For more
information, see Using text moderation.
Speech-to-text, text-to-speech, and real-time translation use Azure Cognitive Services to power these
functionalities. We recommend associating the activation of these capabilities under the Ease of Access player
settings. For information about rates and pricing, see PlayFab pricing and Party pricing.
To learn more, see Understanding how Party chat works. For more guidance on how to use the accessibility
features that are provided by Party, see Text-to-speech guidelines and Speech-to-text guidelines.

Capabilities designed for multiplayer games


Efficient game states and logic delivery
Game states and logic are essential to games. When synchronizing game states, your game is responsible for
deciding when to submit data messages to Party and what these payloads mean.
You can make use of the Party transport system to ensure that submitted messages are delivered securely and
efficiently. This can be achieved by using feature options such as guaranteeing delivery (despite internet packet
loss) and automatically fragmenting and reassembling messages that are larger than what the environment
supports.
Together with ongoing connection quality feedback, such as observed latency, you can decide how your game
interprets this information for a response. Tune, predict, or recover in a way that suits your design and
tolerances.

NOTE
Using data transmission in Party is entirely optional. Some games use only the chat features.

Integration ability with custom/existing discovery systems—players finding other players


Discovery is the process that occurs before players start connecting or chatting with one another. Games
typically have a discovery or signaling mechanism in place to help players find one another before initial
connectivity information can be shared.
Party integrates well with custom or existing discovery systems such as social platforms with invitation systems.
What this means is that after players have found one another through this external system, you would pass
Party suitable connection information to help you set up communication.
Policy enforcement for connectivity and communication
Games have policies in place to determine if real-time chat or data communication between players should be
allowed. Party is able to enforce these policies efficiently through the use of connectivity, voice chat, and text
chat API functionalities—together or independently.
Your game is responsible for defining and determining what these policies are. This is based on gameplay,
privacy, and privilege implementation. For example, restricted accounts can chat only with players who are
friends and must be on a particular social platform (limiting chat capabilities for players who are on behavioral
bans) or simply enforcing gameplay rules to allow only players who are on the same/opposing team to chat.
We have a helper module for the Xbox Live social platform. It helps takes care of common tasks that are needed
to integrate their privilege ecosystems with Party. For more information, see Party Xbox Live Helper Library.

See also
Party overview
Getting started with Party
Multiplayer servers
Multiplayer
Matchmaking
Party and direct peer-to-peer connections
Getting started with Azure PlayFab Party
5/24/2022 • 3 minutes to read • Edit Online

This topic describes how to set up the development environment for Azure PlayFab Party and start using it.

Prerequisites
You need a PlayFab account, and you must enable the Party feature to start using Party.
1. Create/sign in to your PlayFab account. For instructions, see Quickstart: Game Manager.
2. Enable Party feature via Game Manager from your PlayFab account.

Download and set up Party SDK


Like the PlayFab SDKs, we have Party SDKs for different platforms and game engines. Select and download the
one that you need. For download links, see Party SDKs.
After installing the SDK, you might want to run a sample to see how Party works before you start writing code.
For more information, see the Run a sample section.
If you're using Party in Xbox and PC titles, we recommend that you use the Party Xbox Live Helper Library to
ensure consistent functionality and behavior. This library helps your title meet Xbox Live requirements. To learn
more, see Xbox requirements.

Start using Party


Now that you've finished the setup, you're ready to make your first API call and use more Party features.
To start making Party API calls, you also need the PlayFab Entity Token. Get it via REST calls (GetEntityToken) or
by using the PlayFab SDK. For instructions about how to install the PlayFab SDK, see the Install PlayFab SDK
section. If you're using Xbox Live, you can also get this token from the Party Xbox Live Helper Library.
Here are some quickstart guides to help you make your first API call.
Quickstart for Android
Quickstart for iOS
Quickstart for Unity
Quickstart for Unreal
For a high-level, general overview of all the core features in Party, see Party SDK quickstart.

Useful resources
Run a sample
Running a sample is a helpful way to learn how Party works. To download a sample, go to Party samples. If you
have questions or need help, go to PlayFab forums.
Install the PlayFab SDK
You can use the PlayFab SDK to get the PlayFab Entity Token. The PlayFab SDK is needed when you want to use
other PlayFab functionalities such as economy and leaderboards.
1. Install the version of the PlayFab SDK that you need—select by languages, game engines, or frameworks.
2. Associate your game's PlayFab title ID with the PlayFab SDK. If you need to find out what title IDs are or
where to find them, see Your studios and titles.

Key concepts
To help you design and harness the full power of Party, following are some concepts that cover different key
areas.
Party objects and their relationships
Know what the key objects are and how they relate to each another. This information provides you with a
basic understanding of the overall data communication architecture.
Party chat basics
Understand how chat works. Learn which key objects need to be created and defined to implement chat.
Party invitations and the security model
Learn how to limit access to a network as a way to protect the integrity of your own network. Understand
how you can effectively use invites as part of your security design.
Party interacts with your discovery flows
Party can be used with other PlayFab multiplayer features. These features enable players to find other
players so that they can play together. Learn how matchmaking, lobby, and other features can help in this
discovery process.
Party API reference documentation
Get more details about parameters, return values, and behaviors when invoking the C/C++ libraries.
Party UX guidelines for Text-to-speech and Speech-to-text
Understand the best practices for designing user experiences. Be informed about our recommendations
around chat and data communication user interfaces.

See also
Party overview
Party features
Party SDKs
Party samples
Multiplayer servers
Multiplayer
Matchmaking
Party samples
5/24/2022 • 2 minutes to read • Edit Online

This topic lists all the Azure PlayFab Party samples that are currently available.
If there's a specific sample that you'd like to have, let us know by writing a post on our forums.
Access to samples for Nintendo Switch, PlayStation®4, PlayStation®5, Google Stadia, PC (GDK), and Xbox
(GDK) requires special approval and adherence to platform policies. For more information, see Request access
for SDKs and samples.

List of samples
SA M P L E DESC RIP T IO N P L AT F O RM / O P ERAT IN G SY ST EM

Chat app Demonstrates Party chat usage with Windows 10, Windows 8.1, Windows
full speech-to-text and text-to-speech 7, Android, iOS, Stadia, Switch,
capabilities. PlayStation 4, PlayStation 5

Bumble Rumble Demonstrates usage of Party Windows 10, Windows 8.1, Xbox (XDK)
networking, matchmaking, and
accessible voice chat—full speech-to-
text and text-to-speech capabilities. It
doesn't include Xbox Live requirements
and game invites.

NetRumble Demonstrates how to use Party, Party PC and Xbox (GDK)


Xbox Live Helper Library, and Xbox
Services API's (XSAPI) Multiplayer
Manager (MPM) together, meeting
Xbox Live requirements. It also shows
how to send game invites and join a
session.

See also
Party SDKs
Party overview
Getting started with Party
Enabling PlayFab Party
5/24/2022 • 2 minutes to read • Edit Online

This tutorial will get you up and running quickly by showing you in a few steps how to enable the use of PlayFab
Party with the PlayFab Party demo app.
For more on the PlayFab Game Manager, see the Game Manager quickstart.

NOTE
You must launch your title on Game Manager before shipping your title to avoid Dev Mode limits. Failing to do so can
cause your title to not function as more players engage in your game.

Enable PlayFab Party in Game Manager


1. Log into PlayFab and open the game title for which you want to enable PlayFab Party.
2. Select the Multiplayer section.
3. Select the Par ty tab.
4. Click Enable .
Party SDK quickstart
5/24/2022 • 10 minutes to read • Edit Online

This quickstart is intended to be a high-level overview of PlayFab Party's core features. PlayFab Party was
designed to be cross-platform from the ground up. We've structured these quickstarts in the same way, where
most of the information applies to all platforms, and platform-specific prerequisites and steps are described in
the linked documents.
In this quickstart, critical pieces of functionality are highlighted via explanatory text and code snippets. However,
note that this is not a step-by-step walk-through.
For a deeper understanding, consult the linked reference and conceptual documentation, and per-platform
sample applications.

Platform Prerequisites
Before you start this quickstart, perform any necessary platform-specific setup as specified in the following
topics:
1. Android prerequisites
2. iOS prerequisites
3. Nintendo Switch prerequisites
4. Xbox XDK prerequisites
When you finish the platform-specific steps, continue with the rest of the steps in this topic to set up PlayFab
Party.

IMPORTANT
Follow these steps to Enable PlayFab Party.

Log into your PlayFab title and obtain an entity token and entity ID
To initialize and use Party, you must log in to PlayFab. You can use PlayFabClientAPI::LoginWithCustomID or a
platform-specific login method to do this.
Once you execute login, PlayFab returns an entity ID and entity token as part of the LoginResult. These two key
pieces of information are used to initialize a Local user instance for PlayFab Party.
An example code snippet for logging in with a custom ID as implemented in PlayFabManager.cpp is shown
below:
PlayFabClientAPI::LoginWithCustomID(
loginRequest,
[this, callback, userId](const LoginResult& loginResult, void*)
{
// Sign in was successful.
DEBUGLOG("PlayFab::signin -- Login with custom id callback\n");

// Save the PlayFab id and entity data for Party authentication.


m_playfabId = loginResult.PlayFabId;
if (loginResult.EntityToken.notNull() && loginResult.EntityToken->Entity.notNull())
{
m_entityKey = loginResult.EntityToken->Entity;
m_entityToken = loginResult.EntityToken->EntityToken;
}

After successfully obtaining the entity ID and entity token from PlayFab, you can proceed with enabling and then
initializing Party.

Initialize PlayFab Party


Before continuing with this section, it is recommended to read the PlayFab Party objects and their relationships
document and code comments in the public Party.h header. This provides a deeper understanding of the
following operations.
At a high level, initializing Party involves the following steps:
1. Get a singleton reference to the PartyManager and initialize it.
This is the primary management class for interacting with the Party library.

auto& partyManager = PartyManager::GetSingleton();


PartyError err;

//Only initialize the party manager once.


if (m_partyInitialized == false)
{
// Initialize PlayFab Party
err = partyManager.Initialize(titleId);
if (PARTY_FAILED(err))
{
DEBUGLOG("Initialize failed: %s\n", GetErrorMessage(err));
return;
}

m_partyInitialized = true;
}

2. Create a local user object.


This local user object is used to represent a local user on the device (PC, console, phone, ...) when performing
networking and chat operations. The local user object is initialized with the PlayFab Entity ID.
//Only create a local user object if it doesn't exist.
if (m_localUser == nullptr)
{
PartyString entityId = Managers::Get<PlayFabManager>()->EntityId().c_str();
PartyString entityToken = Managers::Get<PlayFabManager>()->EntityToken().c_str();

// Create a local user object


err = partyManager.CreateLocalUser(
entityId, // User id
entityToken, // User entity token
&m_localUser // OUT local user object
);

if (PARTY_FAILED(err))
{
DEBUGLOG("CreateLocalUser failed: %s\n", GetErrorMessage(err));
return;
}
}

3. Create a chat control and set the audio input and output channel where Party will receive or forward data.
The chat control object manages the chat operations for the user on the specific device.
// Only create local chat controls if they don't exist.
if (m_localChatControl == nullptr)
{
PartyLocalDevice* localDevice = nullptr;

// Retrieve the local device


err = partyManager.GetLocalDevice(&localDevice);

if (PARTY_FAILED(err))
{
DEBUGLOG("GetLocalDevice failed: %s\n", GetErrorMessage(err));
return;
}

// Create a chat control for the local user on the local device
err = localDevice->CreateChatControl(
m_localUser, // Local user object
m_languageCode, // Language id
nullptr, // Async identifier
&m_localChatControl // OUT local chat control
);

if (PARTY_FAILED(err))
{
DEBUGLOG("CreateChatControl failed: %s\n", GetErrorMessage(err));
return;
}

// Use system default settings for the audio input device


err = m_localChatControl->SetAudioInput(
PartyAudioDeviceSelectionType::SystemDefault, // Selection type
nullptr, // Device id
nullptr // Async identifier
);

if (PARTY_FAILED(err))
{
DEBUGLOG("SetAudioInput failed: %s\n", GetErrorMessage(err));
return;
}

// Use system default settings for the audio output device


err = m_localChatControl->SetAudioOutput(
PartyAudioDeviceSelectionType::SystemDefault, // Selection type
nullptr, // Device id
nullptr // Async identifier
);

if (PARTY_FAILED(err))
{
DEBUGLOG("SetAudioOutput failed: %s\n", GetErrorMessage(err));
}

4. Set the transcription and translation options.


Transcription and translation are optional chat features that can significantly increase accessibility of your
game. You can find more information about these features in the Chat Overview.
// Get the available list of text to speech profiles
err = m_localChatControl->PopulateAvailableTextToSpeechProfiles(nullptr);

if (PARTY_FAILED(err))
{
DEBUGLOG("Populating available TextToSpeechProfiles failed: %s \n", GetErrorMessage(err));
}

// Set transcription options for transcribing other users regardless of language, and ourselves.
PartyVoiceChatTranscriptionOptions transcriptionOptions =
PartyVoiceChatTranscriptionOptions::TranscribeOtherChatControlsWithMatchingLanguages |
PartyVoiceChatTranscriptionOptions::TranscribeOtherChatControlsWithNonMatchingLanguages |
PartyVoiceChatTranscriptionOptions::TranslateToLocalLanguage |
PartyVoiceChatTranscriptionOptions::TranscribeSelf;

// Set the transcription options on our chat control.


err = m_localChatControl->SetTranscriptionOptions(
transcriptionOptions, // Transcription options
nullptr // Async identifier
);

if (PARTY_FAILED(err))
{
DEBUGLOG("SetTranscriptionOptions failed: %s\n", GetErrorMessage(err));
}

// Enable translation to local language in chat controls.


err = m_localChatControl->SetTextChatOptions(
PartyTextChatOptions::TranslateToLocalLanguage,
nullptr
);

At this point, you have the PlayFab Party initialized in your application or game.
Refer to the NetworkManager::Initialize() code in NetworkManager.cpp in the demo app for a complete
sample.
The next step is to Create and Connect to a Party Network.

Create a Party Network


A Party Network is a secured collection of one or more devices and their authorized users that the game creates
for the purpose of exchanging chat or data communication. This typically aligns with a game's multiplayer
session or chat "lobby" concept. You can only send messages to players inside your own network.
The following code snippet shows how we can create a Party Network.

// Initialize an empty network descriptor to hold the result of the following call.
PartyNetworkDescriptor networkDescriptor = {};

// Create a new network descriptor


err = PartyManager::GetSingleton().CreateNewNetwork(
m_localUser, // Local User
&cfg, // Network Config
0, // Region List Count
nullptr, // Region List
&invitationConfiguration, // Invitation configuration
nullptr, // Async Identifier
&networkDescriptor, // OUT network descriptor
nullptr // applied initialinvitationidentifier.
);
Once the function call to CreateNewNetwork() succeeds, a network descriptor PartyNetworkDescriptor object will
be returned/populated. The descriptor contains the data required by other players to connect to a network.
Refer to the API Reference Documentation for information about the other function parameters.

Connect to a Party network


Once a Party network has been created, Invitations are used to control which users can join the network.
Invitation information therefore needs to be shared with other users. For this, PlayFab Matchmaking, another
matchmaking service, in-game invite services, or platform invite services can be used.
The simplest Invitation type is an open invitation that consists of a network descriptor and is used here. For
detailed information of all Invitation types and the security model, refer to Invitations and the security model.
We implemented simple matchmaking using PlayFab CloudScripts in the demo samples, which works as
follows:
1. The user creating the network creates a json key value pair with a room number as key and the network
descriptor as value.
2. They store this json object in playfab backend via a CloudScript function save_network_descriptor .
3. Any player that wishes to join the same network (abstracted away through the concept of a chat room),
queries for the network descriptor associated with the room they seek to join. This is accomplished via
calling the CloudScript function get_network_descriptor .

The full code of the CloudScript functions are given below for reference:

// Used to store a network descriptor on the server retrievable by the roomId


// Inputs:
// roomId - The hash key used to store and retrieve the network descriptor.
// networkDescriptor - The network descriptor used to connect to a party network.
//
handlers.save_network_descriptor = function (args, context)
{
if (args && args.hasOwnProperty("roomId"))
{
var roomId = args.roomId;
}
else
{
return;
}

if (args && args.hasOwnProperty("networkDescriptor"))


{
var networkDescriptor = args.networkDescriptor;
}
else
{
return;
}

try {
server.CreateSharedGroup({ SharedGroupId: roomId });
} catch(err) {
log.info("Shared group " + roomId + " could not be created.");
log.error(err);
}

var updateRequest = {
SharedGroupId: roomId,
Data: {
Data: {
"network": networkDescriptor
}
};

server.UpdateSharedGroupData(updateRequest);
};

//
// Used to retrieve a previously stored network descriptor by roomId.
// Inputs:
// roomId - The hash key used to store and retrieve the network descriptor.
//
handlers.get_network_descriptor = function (args, context)
{
if (args && args.hasOwnProperty("roomId"))
{
var roomId = args.roomId;
}
else
{
return;
}

try
{
var getRes = server.GetSharedGroupData({ SharedGroupId: roomId });
return getRes.Data;
}
catch(err)
{
return;
}
};

Once each player has a way to retrieve the network descriptors by selecting a room and calling the CloudScript
functions, they can use the network descriptor thus retrieved to join the Party Network.
The following steps are required to successfully join a PlayFab Party Network:
1. Retrieve the network descriptor as a string by executing the above-mentioned PlayFab CloudScript
function.
2. Deserialize the network descriptor from the network descriptor string.
3. Connect to the Party Network.
4. Authenticate the local user for the network.
5. Connect the local chat control to the network so that we can use VOIP.
6. Establish a Party Network endpoint for game message traffic.

PartyNetworkDescriptor networkDescriptor = {};

// Deserialize the remote network's descriptor


PartyError err = PartyManager::DeserializeNetworkDescriptor(descriptor, &networkDescriptor);

if (PARTY_FAILED(err))
{
DEBUGLOG("ConnectToNetwork failed to deserialize descriptor: %s\n", GetErrorMessage(err));
errorCallback(err);
return;
}

// This portion of connecting to the network is the same for


// both creating a new and joining an existing network.
// both creating a new and joining an existing network.

PartyError err = PartyManager::GetSingleton().ConnectToNetwork(


&descriptor, // Network descriptor
nullptr, // Async identifier
&m_network // OUT network
);

if (PARTY_FAILED(err))
{
DEBUGLOG("ConnectToNetwork failed: %s\n", GetErrorMessage(err));
errorCallback(err);
return false;
}

// Authenticate the local user on the network so we can participate in it


err = m_network->AuthenticateLocalUser(
m_localUser, // Local user
networkId, // Invitation Id
nullptr // Async identifier
);

if (PARTY_FAILED(err))
{
DEBUGLOG("AuthenticateLocalUser failed: %s\n", GetErrorMessage(err));
errorCallback(err);
return false;
}

// Connect the local user chat control to the network so we can use VOIP
err = m_network->ConnectChatControl(
m_localChatControl, // Local chat control
nullptr // Async identifier
);

if (PARTY_FAILED(err))
{
DEBUGLOG("ConnectChatControl failed: %s\n", GetErrorMessage(err));
errorCallback(err);
return false;
}

// Establish a network endoint for game message traffic


err = m_network->CreateEndpoint(
m_localUser, // Local user
0, // Property Count
nullptr, // Property name keys
nullptr, // Property Values
nullptr, // Async identifier
&m_localEndpoint // OUT local endpoint
);

if (PARTY_FAILED(err))
{
DEBUGLOG("Failed to CreateEndpoint: %s\n", GetErrorMessage(err));
errorCallback(err);
return false;
}

Send a message to another network device or endpoint


Once you've connected to the Party Network, you can send a message using the local endpoint object.
if (m_localEndpoint && m_state == NetworkManagerState::NetworkConnected)
{
auto packet = message.Serialize();

// Form the data packet into a data buffer structure


PartyDataBuffer data[] = {
{
static_cast<const void*>(packet.data()),
static_cast<uint32_t>(packet.size())
},
};

// Set delivery options for guaranteed and sequential delivery.


PartySendMessageOptions deliveryOptions =
PartySendMessageOptions::GuaranteedDelivery |
PartySendMessageOptions::SequentialDelivery;

// Send out the message to all other peers


PartyError err = m_localEndpoint->SendMessage(
0, // endpoint count; 0 = broadcast
nullptr, // endpoint list
deliveryOptions, // send message options
nullptr, // configuration
1, // buffer count
data, // buffer
nullptr // async identifier
);

if (PARTY_FAILED(err))
{
DEBUGLOG("Failed to SendMessage: %s\n", GetErrorMessage(err));
}
}

The full code is available in NetworkManager.cpp.

Receive a message and render it on the local device


The final step is receiving messages sent by remote Party members and rendering (playing) them on your
device.

IMPORTANT
While creating the chat control in one of the previous steps, you've already set up the audio input and output devices
which will be used by Party to send, receive and render audio data. To receive the audio messages, you'll also need to set
the appropriate chat permission between each chat control if you want audio to flow. By default, the chat permissions are
set to NONE. For more information, refer to the Chat Permissions article.

The processing of other messages from the Party layer is best accomplished in a dedicated update thread or a
high-frequency game loop. The game loop should be set up to run every frame and receive messages from the
Party Manager via the StartProcessingStateChanges() function.
For a complete description of all the state changes refer to the Party Reference Documentation. Alternatively,
you can refer to the NetworkManager.cpp for an example of how to process each state change.

Conclusion
In this quickstart, we walked through the key pieces of PlayFab Party and saw how to interact with them.
We encourage you to take a look at the complete Reference and Conceptual documentation as well as samples
for a deeper understanding of the systems.

Next steps
For additional platform-specific guidance for application, see:
Xbox and Xbox Live
Xbox Requirements
Using MPSD
PlayFab Party objects and their relationships
5/24/2022 • 13 minutes to read • Edit Online

Successfully using the power and flexibility of the PlayFab Party API begins with understanding the following
crucial objects defined in its scope:
Device - A distinct instance of the game executing on a physical device. A local device exists whenever the
API is being used.
User - An individual logged-on player, or more precisely, a PlayFab title_player_account Entity that the
game has actively provided to PlayFab Party for authentication and identification purposes. One or more
users are associated with a given device.
Network - A secured collection of one or more devices and their authorized users that the game creates for
the purpose of exchanging chat or data communication. This typically aligns with a game's multiplayer
session or chat party concept.
Endpoint - An abstraction for sending and receiving data within a network. An endpoint may represent a
device, a user, or any desired game-specific concept.
Chat control - A representation of a user specifically for configuring, originating, and targeting voice and
text chat in one or more networks.

Object relationships
As a simplified conceptual hierarchy, networks contain devices, which in turn contain users, optional endpoints,
and optional chat controls. For example:

While simple enough to understand, the preceding relationship diagram is actually an incomplete depiction of
PlayFab Party's capabilities and can be misleading if taken on its own. In reality, the Party API supports devices
connecting to multiple networks at once. For example, one might desire to maintain communication with a
group of friends over time as that same group also joins and leaves separate larger game sessions with
strangers. Considering this broader scenario allows us to better grasp the relationships between these objects.
It might feel intuitive to conceptualize a device as belonging to networks, but this is not the case. It is more
correct to realize that devices participate in networks. As such, only a single device API object, whether remote
or local, is ever created by the Party library when a particular instance is encountered, regardless of the number
of networks it shares with your local device.
As an example, the following diagram shows two networks and three devices with users, chat controls and
endpoints. Device A and its two chat controls (with associated users) are participating in Network 1, while
Devices B and C have connected both to that network and to Network 2 with a single chat control (and
associated user) each. All devices have created one or two endpoints in each network where they're connected:

In the above diagram, every device sees a single instance of all three devices and their chat controls, since they
have at least one network in common with each other. Device A only knows about Endpoints 1-4 in Network 1,
but Devices B and C can see the Endpoints 5-7 they created in Network 2 as well.
If Device C were instead only participating in Network 2 in the above diagram and not both networks, then:
Device C obviously would not have been able to create Endpoint 4 in Network 1, nor see Endpoints 1-3 that
the others had created within it.
Device C would not know about Device A or its two chat controls only in Network 1.
Device A would similarly not see Device C or its chat control only in Network 2.
Device B however would still see all devices and their chat controls since it's still in both networks.
So, despite devices and chat controls being "outside" a strict hierarchical tree relationship with networks, it's
important to note that a game instance will never actually encounter a remote device or chat control without the
context of an accompanying network. If the local and remote device or chat control have at least one network in
common, the remote object may be visible. But if there are no common networks, then the remote object will
never be created.

NOTE
Games are not required to connect to more than one network simultaneously in order to use PlayFab Party successfully.
You can learn more about whether and how to use multiple networks in a subsequent advanced topic.

Common object attributes


All of the above objects have well-defined lifetimes. Each is created and destroyed either directly by the local
game instance or using standardized notification mechanisms that are only signaled during a time window of a
game's choosing. Working with notifications is described in more detail in a later topic.
All of the PlayFab Party API objects also support the concept of a custom context, which is simply a way to store
an optional, local-only "shortcut" pointer or value with the object. This makes it easy to go from PlayFab Party
objects back to your corresponding private game objects in memory (if any) without needing to perform an
inefficient lookup. These values aren't transmitted remotely, since pointer values only have meaning to the local
game instance.
Finally, all of the above objects except network have a specialized "Local" sub-object containing methods and
properties that are only available to the local device that owns the object.
For example, there's a base PartyEndpoint object used to represent any local or remote endpoint, and a more
specific PartyLocalEndpoint object that can be retrieved via PartyEndpoint::GetLocal() only if that endpoint was
actually created by the local device. This is where the PartyLocalEndpoint::SendMessage() method for
transmitting game data is exposed since it wouldn't make sense for one device to be able to somehow transmit
data from a completely different remote device's source endpoints.
When using the C++ PlayFab Party interface (recommended), objects are exposed as C++ class instances. When
using the flat C interface, objects are represented by handle values.

The roles of all major objects in more detail


1. Manager ( PartyManager )
2. Network ( PartyNetwork )
3. Device ( PartyDevice and PartyLocalDevice )
4. User (User Entity IDs and PartyLocalUser )
5. Endpoint ( PartyEndpoint and PartyLocalEndpoint )
6. Chat Control ( PartyChatControl and PartyLocalChatControl )
7. State Change ( PartyStateChange )
Manager
In addition to the objects summarized earlier, the PlayFab Party API also exposes a top-level PartyManager
singleton object.
This utility/organizational object is used largely as a starting point to begin working with the other objects. This
is where new networks and local users are initially created, for example. All asynchronous operation
completions and notifications are also centralized here. Perhaps most fundamentally, this is where the PlayFab
Party library itself is initialized before use and cleaned up when no longer needed.
Network
A PartyNetwork object represents a secured collection of participating devices, their authorized users, and any
accompanying endpoints or chat controls. Networks are initially created by the game as empty, but devices
connect to them and authenticate at least one local user into the network. Networks that don't have any
authenticated users are automatically destroyed after a timeout.
In order to connect to them, networks are referenced using network descriptors. These are largely opaque
binary structures containing the information that PlayFab Party needs internally to identify and locate the
network. The API provides methods for serializing the structures to web-service-friendly strings and back so
they can be exchanged with other devices using common social platform invite mechanisms, PlayFab
Matchmaking, or other external rendezvous mechanisms outside the scope of PlayFab Party itself.

NOTE
The network descriptor for a network can change in rare circumstances. Games should be prepared for notifications of
such changes, and then update or re-advertise the new network descriptor for an existing network in order to avoid
problems with additional devices connecting.

Even with a network descriptor available, gaining access to a network is restricted to users that the game
authorizes to join the particular network in advance (or perhaps "just-in-time" when the user has been added to
a corresponding externally-managed gameplay session, for example). This user authorization is done during
network creation and through subsequent creation and revocation of invitations as described in more detail in
the topic Invitations and the security model.
Games can choose to use invitations to restrict entry to only users' friends, or to prevent malicious players from
joining the network.
Devices can connect to more than one network at a time. You can learn more about whether and how to use
multiple networks in a later topic.
The kinds of actions that can be taken on PartyNetwork objects include authenticating local users into it,
connecting and enumerating chat controls, creating and enumerating endpoints, or getting network-wide
performance information.
Device
The PartyDevice object represents a distinct instance of the game and its PlayFab Party library code executing
on a physical device. Most operations aren't performed on PartyDevice objects themselves; rather they're an
organizational mechanism for defining which endpoints or chat controls belong to that game instance,
particularly for platforms and games that support more than one local user simultaneously. PlayFab Party uses
this relationship knowledge to optimize transmission of game data and chat by only sending one copy of a
message even if multiple targets on the device need to receive it, for example.
Remote PartyDevice objects are "byproducts" of connecting to a network and authenticating a user into that
network. They're only created when valid, authenticated remote users associated with the device are
participating in a network to which the local device is also connected. Correspondingly, they are also destroyed
once that is no longer true.
On the other hand, the PartyLocalDevice specialized sub-object is always available for the local game instance
to reference as long as PlayFab Party is initialized. It is never explicitly created or destroyed.
User
A PlayFab Party user is a unique human player for whom the game has performed PlayFab Player Login in order
to acquire a title_player_account Entity ID and token.
Remote users are identified within the PlayFab Party API solely by their Entity ID string associated with chat
controls and optionally with endpoints. They are not represented using a dedicated object. This is because
PlayFab Party doesn't have functionality that meaningfully interacts with arbitrary users, other than for raw
identification and as a label associated with those other objects.
Conversely, for local users there are explicit PartyLocalUser objects, since games own the management of their
lifetimes within PlayFab Party. The game will typically create a PartyLocalUser when the game has successfully
logged that PlayFab player in using the applicable login method, and destroy the PartyLocalUser as appropriate
when that user logs off. For platforms and games that support multiple local players logged in, additional
PartyLocalUser objects should be created for each player.

PartyLocalUser objects are also important because they are the basis of all authentication. A valid local user
must exist in order to either create a new network or to authentication into one.
Authorizing users is described in more detail in the topic covering Invitations and the security model.
Almost every operation requires a PartyLocalUser to be provided or present, even though very few operations
are performed on PartyLocalUser objects themselves.
PartyLocalUser objects are created using the PartyManager object. They can only be explicitly destroyed by their
creators. While they have no direct object representation on remote devices, chat controls and endpoints
associated with them will be destroyed if the owning device removes the PartyLocalUser or disconnects from
the network, gracefully or otherwise.
Endpoint
PartyEndpoint objects are optional but are the core of PlayFab Party data communication for games that
leverage them. Like typical networking sockets, endpoints are an abstracted addressing mechanism for
originating or targeting data messages within a network. They could represent a device, an individual user, or
any arbitrary game-defined concept (e.g., a tank unit) that you'd like to uniquely identify for sending and
receiving messages.
The specialized PartyLocalEndpoint sub-object is for endpoints created in the network by the local game
instance. This is where most endpoint functionality resides. Its PartyLocalEndpoint::SendMessage() transmits
game data payloads from the PartyLocalEndpoint to one or more other PartyEndpoint objects in the same
network. It provides various options for selecting how best to handle Internet packet loss (e.g., guarantee
delivery and/or ordering), to control the tradeoff between low latency versus coalescing multiple messages
from the same or other local endpoints for lower bandwidth usage, and to react when the connection quality
isn't sufficient to support the rate at which the game is sending. You can learn more about transmitting game
data using endpoints in a later topic.
In addition to being a source or destination for data messages itself, each PartyEndpoint object is also assigned
a 16-bit endpoint unique identifier by PlayFab Party that allows you to reference the specific endpoint in
message payloads sent to or from separate PartyEndpoint objects within the network. This provides a
convenient way to avoid the overhead of sending a full, larger user Entity ID string or other identifier it might
represent, for example, without having to build your own peer-to-peer identity agreement negotiation.
PartyLocalEndpoint objects are created using their containing PartyNetwork object. Doing so results in
corresponding PartyEndpoint objects being created on remote devices. An endpoint can be destroyed explicitly
by its creator, or will be destroyed implicitly when the owning device disconnects from the network or the
associated PartyLocalUser object (if one had been specified) is removed from the network.
Chat control
PartyChatControl objects are the mechanism for using PlayFab Party's optional chat communication features.
They represent a particular user's associated audio input/output devices, preferences, and communication
policies.
The specialized PartyLocalChatControl sub-object is also available for chat controls created by the local game
instance. This is where you configure the permissions allowing chat communication to or from remote
PartyChatControl objects, for example, to choose network-wide vs. team-only chat, or to apply platform policy
restrictions. Local chat controls are used for sending chat text, synthesizing text to speech, requesting
transcriptions and translations of voice streams, muting, and more.
PartyLocalChatControl objects must be connected to a network before they will be created as PartyChatControl
objects on remote devices in that same network. A device will always only see a single representative
PartyChatControl object created, even when that device and chat control have connected to more than one
network in common. This helps avoid unnecessary duplication or interruption of audio and text chat messages.
PartyLocalChatControl objects are created using the containing PartyLocalDevice object. A chat control can be
destroyed explicitly by its creator, or will be destroyed implicitly when the owning device disconnects from the
network or the associated PartyLocalUser object is removed from the network.
State Change
PartyStateChange structures are used to inform the game of all asynchronous operation completions, incoming
messages, update notifications, and other API-related events.
To simplify how you work with complex multi-machine interactions over the Internet with unpredictable timing,
PlayFab Party guarantees it won't modify any state it reports from the API except as a result of an explicit call by
the game. But since you do still need a way to learn about remotely initiated operations or unplanned
occurrences that modify local state, PlayFab Party and the game cooperate through a special pair of methods,
PartyManager::StartProcessingStateChanges() and PartyManager::FinishProcessingStateChanges() . These are
called at a point in the game's work loop where it's convenient to handle such updates. The new events are
reported from PartyManager::StartProcessingStateChanges() as an array of zero or more PartyStateChange
structures. Once the game has handled the state changes, the array is returned using
PartyManager::FinishProcessingStateChanges() .

The PartyStateChange structure is not a full object by itself. It's a base header to be cast to a more detailed
structure containing information on the specific type of completion or notification, pointers to the relevant
objects, and any error information.
Working with state changes is described in full detail in a later topic.

Next steps
Learn about PlayFab Party invitations and the security model
Learn how PlayFab Party interacts with your discovery flows
Find out more about PlayFab Party chat communication
See how to work with asynchronous operations and notifications in PlayFab Party
Understanding how PlayFab Party chat works
5/24/2022 • 3 minutes to read • Edit Online

With PlayFab Party you can easily add voice and text communication to your game.
PlayFab Party chat is:
Flexible : Gives you full control of how you want your player to communicate.
Powerful : Uses hardware codec acceleration on supported platforms.
Accessible : Powered by Azure Cognitive Services, speech-to-text, text-to-speech and translation features are
built-in and easy to enable.
Efficient : Having your chat system tightly integrated with your networking layer means voice data get sent
where it needs to go in the most efficient way possible.

Chat basics
To add voice and text communication to your game you will first need to create a PartyLocalChatControl object.
This PartyLocalChatControl object will act as the management object for chat operations related to a specific
local user, allowing you to choose the input and output device, mute state, and accessibility preferences. Each
local user can have no more than one chat control. For a local chat control to communicate with another chat
control, the following requirements must be met:
1. The two chat controls must be in the same network.
2. The chat permissions between the two chat controls must allow audio and/or text communication to flow.
With your local chat control in-hand you are now ready to have it connect to a network by calling
PartyNetwork::ConnectChatControl() . Upon connection, other devices in the network will be notified that your
chat control has joined the network with a PartyChatControlJoinedNetworkStateChange state change. You will also
receive a PartyChatControlJoinedNetworkStateChange for every other chat control already in the network and will
immediately be able to communicate with them.

Audio Inputs and Outputs


Party allows you to choose which audio device(s) will get used by your chat control with the
PartyLocalChatControl::SetAudioInput() and PartyLocalChatControl::SetAudioOutput() methods. Use the
PartyAudioDeviceSelectionType enum to change the behavior of these methods:

PartyAudioDeviceSelectionType::None

When this audio device selection type is chosen, the chat control won't use any audio device. This is the default.
PartyAudioDeviceSelectionType::SystemDefault

When this audio device selection type is chosen, the chat control will attempt to use the system's default
communication device. On Windows, the player can change this device at any time through the Windows Sound
Control Panel and Party will respond to those changes automatically. This selection type is not supported on
Xbox One and generally not recommended if you have more than one local user participating in chat
simultaneously.
PartyAudioDeviceSelectionType::PlatformUserDefault

When this audio device selection type is chosen, PartyLocalChatControl::SetAudioInput() and


PartyLocalChatControl::SetAudioOutput() require that the audioDeviceSelectionContext parameter be set to a
platform user ID. Party then attempts to use the platform default communication device associated with that
user. On Xbox One, the audioDeviceSelectionContext should be the Xbox User ID associated with the user
currently tied to the chat control.
PartyAudioDeviceSelectionType::Manual

When this audio device selection type is chosen, PartyLocalChatControl::SetAudioInput() and


PartyLocalChatControl::SetAudioOutput() will use the audioDeviceSelectionContext parameter as a valid audio
device identifier and will attempt to use any device matching that identifier. Refer to the following table to see
what kind of identifier is supported by PlayFab Party:

P L AT F O RM W H AT TO USE

Windows 7 IMMDevice

Windows 10 IMMDevice or Windows.Media.Devices

Xbox One Please refer to the Xbox One XDK documentation

NOTE
We strongly recommend using PartyAudioDeviceSelectionType::PlatformUserDefault on Xbox One and
PartyAudioDeviceSelectionType::SystemDefault on Windows platforms.

Chat permissions and muting


Party gives you fine-grained control over how your players can communicate with each other. Rather than
specifying teams or channels, Party requires explicitly defining the permissions between each pair of chat
controls. To learn more about chat permissions, muting and how to build common chat scenario, please refer to
the chat permission overview page.

Text chat, translation, and moderation


Party also allows you to send and receive text chat from other chat controls. While the
PartyLocalChatControl::SendText() method will allow you to send text messages to an arbitrary number of chat
controls, you can rest assured that only the chat controls with the appropriate
PartyChatPermissionOptions::ReceiveText chat permission receive the messages.

Text chat translation can also be enabled by calling PartyLocalChatControl::SetTextChatOptions() . By setting the
PartyTextChatOptions::TranslateToLocalLanguage option Party will translate incoming text message to the local
chat control's language. The chat control's language can optionally be configured during chat control creation
and can be accessed by calling PartyLocalChatControl::GetLanguage() . Translation will also be applied to
incoming speech-to-text transcription.
Text moderation is also available for text chat. To learn more about this feature, please refer to the Using text
moderation page.

Accessible chat
Powered by Azure Speech Services, Party can transcribe player voice chat and synthesize speech from text. This
functionality has several uses but was primarily designed as an accessibility aide. We recommend tying
activation of this capability to an ease-of-access player setting. For more guidance on how to use the
accessibility features provided by Party, see text-to-speech guidelines and the speech-to-text guidelines.
Next steps
Find out more about PlayFab Party chat permissions and muting
PlayFab Party text-to-speech and text input UX
guidelines
5/24/2022 • 11 minutes to read • Edit Online

The PlayFab Party library gives game creators the power to engage more players through accessible game chat
options. It provides a means for voice chat to be transcribed to text and for text input to be converted to
synthesized voice. You can implement a custom UI solution for these features in your title. On Xbox and
Windows, you can use platform APIs to implement the relevant UI.
This topic is part one of a two-part series covering UX solutions for speech-to-text and text-to-speech
implementation. Part one focuses on text-to-speech implementation, requirements, and console and PC UI
solutions, while part two focuses on speech-to-text implementation, requirements, and console and PC UI
solutions.

Text-to-speech and speech-to-text scenarios


The following chart guides you through scenarios that players will experience when you enable speech-to-text
and text-to-speech features. It outlines user impact for three stages of the gaming experience: initial setup,
playing a game, and engaging in game chat.

EXP ERIEN C E STA GE SET UP P L AY C H AT M ESSA GE

Goal User enables User enters a User sends User receives


setting multiplayer game communication communication

Action Speech-to-Text Launches game User speaks User reads team's


voice replies
Alternative for Enters MP lobby converted to text in a
hearing voice replies speech-to-text chat
Overlay opens when overlay
game chat is initiated

Text-to-speech Launches game User types replies User hears team


using platform member's voice
Alternative for Enters MP lobby supported input replies
speaking voice replies methods
Game displays
method for text input Typed messages are
(keyboard, input field, converted to
etc) synthesized voice

UI Narration (in- User is guided by the For text messaging For text messaging
game) Xbox OS synthesized systems: Games use systems: Games use
voice to launch game the Speech synthesis the Speech Synthesis
Alternative for API to guide the user API to narrate replies
reading in-game Game uses the to launch the Xbox
menus and text Speech Synthesis API OS keyboard
replies to narrate menu
options leading the
user to the MP lobby
EXP ERIEN C E STA GE SET UP P L AY C H AT M ESSA GE

Narrator (Xbox OS) User is guided by the For text messaging N/A
Xbox OS synthesized systems: A virtual
Alternative for voice to launch game Keyboard is narrated
reading Xbox menus as the user types a
message

Understanding the API


Text-to -speech
Types of text-to-speech
Party supports two types of text-to-speech - Voice Chat and Narration . The Voice Chat type is for the scenario
where a user elects to use text-to-speech audio as their speaking voice for voice chat communication. When this
page discusses Party and text-to-speech, it's typically talking about this scenario. The Narration type is for the
scenario where a user should have text-to-speech audio played to their audio output. This is primarily to support
the "voice auditioning" scenario where a user compares audio between text-to-speech voice options to select the
profile they prefer to use in Voice Chat scenarios. Although this can be used for arbitrary, game-defined
narration scenarios, each platform typically provides a more flexible solution for in-game narration, such as the
Speech Synthesis API on Xbox and Windows. Each method used to start a text-to-speech operation takes a
PartySynthesizeTextToSpeechType parameter that specifies which of the two text-to-speech scenarios is being
used.
Text-to-speech voice profiles
A text-to-speech voice profile defines the audio characteristics used to generate text-to-speech audio. Profiles
vary by language, locale, and gender. There may be multiple options for each combination. Party supports all
profiles supported by Azure Cognitive Services. Refer to the Language support reference for a complete list of
supported languages and voice options.
The profile options can also be enumerated by the Party library. The first step is to start an asynchronous
operation that will populate the text-to-speech profiles via
PartyLocalChatControl::PopulateAvailableTextToSpeechProfiles() . Once the operation completes, indicated by
PartyManager::StartProcessingStateChanges() providing a
PartyPopulateAvailableTextToSpeechProfilesCompletedStateChange , the profiles can be queried via
PartyLocalChatControl::GetAvailableTextToSpeechProfiles() .

Configuring the text-to-speech voice profile


Before any text-to-speech can be generated by the Party library, the title must configure the text-to-speech voice
profile. An asynchronous option to configure the profile can be started via
PartyLocalChatControl::SetTextToSpeechProfile() . The completion of the operation is indicated by
PartyManager::StartProcessingStateChanges() providing a PartySetTextToSpeechProfileCompletedStateChange .

Synthesizing text-to-speech
Once the title has configured a text-to-speech voice profile, text can be synthesized to speech audio via
PartyLocalChatControl::SynthesizeTextToSpeech() . For the Voice Chat scenario, the audio data will appear as
though it was captured "naturally" by the microphone associated with the user starting the text-to-speech
operation. This is akin to the user holding the microphone to a computer that is talking on their behalf. For the
Narration scenario, the audio data will be played to the user's audio output.
Synthesizing text-to-speech is an asynchronous operation; the completion of the operation is indicated by
PartyManager::StartProcessingStateChanges() providing a PartySynthesizeTextToSpeechCompletedStateChange .

Although a voice profile must be configured before synthesizing text-to-speech, it isn't necessary to wait for the
asynchronous operation started by PartyLocalChatControl::SetTextToSpeechProfile() to complete before calling
PartyLocalChatControl::SynthesizeTextToSpeech() . If a profile operation is in progress, the text-to-speech
operation will be queued and start after the profile operation completes.
Text messaging
In addition to text-to-speech, Party supports traditional text messaging. Although many titles tie text-to-speech
to text messaging, that isn't a requirement - Party supports text-to-speech and text messaging as independent
features. For more information, see Understanding chat.

Text-to-speech UX
Text-to-speech enables a person to use the platform to send a synthesized voice stream to the active game chat
participants. This is great for enabling the person to participate when there is no text chat-based system
available, and all communication is active through the in-game voice chat.
Discovery
For Xbox and Windows, users can find text-to-speech and speech-to-text settings in the Accessibility section
under Settings in Xbox Home (Xbox console) or Xbox App (Windows 10). The settings are controlled via toggle
buttons that enable or disable the features for all Xbox games specific to the user profile that integrate with the
platform settings. For all other platforms, refer to their accessibility guidelines for text-to-speech and speech-to-
text setting locations.

NOTE
If your game chooses to add additional settings that are game specific only, then they should be placed inside your game.
In general, accessibility options belong under the game’s settings/options menu. Ideally, settings should be available as a
dedicated button press and accessible from any screen or, at least, the Pause menu.

Text input/output options


A title is responsible for prompting and accepting text . This could be a custom text entry field or the
platform-provided keyboard. The resulting entry can then be passed into PlayFab Party to be processed into a
synthetic stream. That stream is sent to the other players in the chat session as voice. The receiving end would
handle this voice stream in the same way they would another voice stream from a user speaking through a
microphone.
1. Console OS vir tual keyboard (Xbox console example)

NOTE
The keyboard will still appear when a gamepad is installed. It will not appear when a hardware keyboard is
installed.
2. PC OS vir tual keyboard (Windows 10 example)
The PlayFab Party API supports receiving input across all platforms. However, text input components are
not provided consistently across those platforms.
On the Xbox console, games can rely on the virtual keyboard. It has its own input box, which accepts
text that is then provided to the title.
On Windows, games can rely on the virtual keyboard with a caveat - it doesn't have an input box. This
means that the game must provide a text input box to accept the keystrokes generated by the virtual
keyboard. Even if the game does not support traditional text chat, text input may be required for text-
to-speech support.
UX recommendation (Windows )
Cross-platform games that do not support traditional text messaging must provide a text input box to
accept keystrokes to support text-to-speech.

3. A game-provided custom keyboard (console example)

NOTE
The phrases used here specific to the sample game being shown.

Games have full control over visibility.


Games can enhance the keyboard to include phrases for quick replies.

Quick Chat: A solution for everyone


Consider your player's chat activity, discussion type, and screen objectives. For instance, during active gameplay
sessions, launching a keyboard and typing replies would be cumbersome using a controller, but may be critical.
Providing a method for users to quickly choose from a list of predefined replies would go far in solving this
problem. For users who enable narration, each predefined reply would be narrated. The list of replies would be
pre-scripted, so translation would increase in accuracy. The game would have control over contextual, game-
specific terms appropriate for their players.
Here are two examples, using the Xbox console and Windows 10 platforms:
1a. Phrase list mapped to the D-pad
Pressing a direction (up, down, left, right) on the directional pad (D-pad) opens the chosen category. Once the
category list is open, D-pad directions apply to the choices within that category. To swap categories, the user
waits for the window to close (two seconds of inactivity) and then chooses an alternate D-pad direction to open
a new list of replies.

1b. Phrase list mapped to a keyboard


Pressing a number key (1-4) opens the chosen category. Once the category list is open, the number keys apply
to the choices within that category. To swap categories, the user waits for the window to close (two seconds of
inactivity), and then chooses an alternate number key to open a new list of replies.

1c. Phrase list mapped to a keyboard with customizable reply settings


Take this feature one step further by allowing the user to choose from a range of responses.
Console example : For keyboard and controller design template natives, see Resources.
In the first image, the Options menu includes a Chat section. This screen displays default and user-selected
replies, listed under four categories of conversation types (compliments, instructional, and so on).
Each category is mapped to a single-tap D-pad direction. Each reply is mapped to a double-tap D-pad direction.
A user can select a reply to edit by pressing A.

In the second image, a pop-up display offers a list of ten replies. A user can select up to four, each mapped to a
D-pad direction based on the order of selection.

Controller schematic for mapping replies


Some games already provide custom controller mapping for a variety of gameplay preferences. This example
proposes an alternative controller schema for text-to-speech and speech-to-tet. Users can select from a list of
predefined replies and map to four D-pad directions. The left and right bumpers scroll through categories; the Y
button launches a virtual keyboard for custom replies.
During a game session, a user can swap control schemas with a dedicated button press (assigned by the game).
In this case, the B button exits this mode.
Quick Chat reply guidance: A method to get gamers engaged
What if gamers could personalize a quick chat solution that enhances player-to-player exchange? What if there
were a solution that maximizes game performance while minimizing communication barriers? Quick Chat
comes close, by allowing users to choose from a list of predefined replies. Typically, however, these replies have
been limited, redundant phrases that appear automated and boring. The guidelines below explore a strategy for
keeping players engaged.
Goal: Make this behavior automatic
If Quick Chat satisfies a need repeatedly, a habit can be formed. Consider ways to trigger responses and how
that can meet the conversational need at that moment.
Quick Chat use cases
Conversational : Players want to engage to facilitate team activity or build deeper social connections.
Simplicity : A Quick Chat solution must be easy to access during times of high-intensity activity.
Anonymity : Players who normally avoid voice chat have a way to participate.
1. Var y replies Provide a large collection of reply options. This will contribute to the spontaneity normally
achieved in dynamic voice conversations. Users will be less likely to get bored with the same reply
options and replies will seem less automated.
2. Surface the solution at the time the need arises
Make Quick Chat available anytime game chat is engaged.
Use a dedicated button-press to launch Quick Chat replies.
Default to a category that is contextual to current game activity. For example, when a user scores, the
default category is "Compliments."
3. Keep replies focused and concrete This is mostly to keep cognitive load low. Users should be able to
read an entire message effortlessly.
Make replies relevant to gameplay and its category.
Use short phrases and one-syllable words that are most commonly used in your game.
Use words that you can instantly visualize.
4. Use humor Banter is a common form of taunting that addresses players in a friendly manner. This is
different from griefing, where all too often, users are harassed. If replies are clever, relevant, and varied,
some users may not resort to inappropriate choices.
5. Be relative to skill and progress
Offer chat preferences that include basing replies on progression and skill level.
Surface suggested replies that a user can communicate to other team members. These options would
be contextual to current game activity. For example, "Anyone have an axe to beat this zombie?"
6. Focus on the emotions Replies that communicate certain target emotions can help make their
experience more relatable.

Conclusion
PlayFab Party text-to-speech and speech-to-text APIs are highly effective features for including a wider range of
users in a game and gaming conversations. The more gamers engage and develop relationships, the more likely
they are to continue playing. This guidance will help ensure the best possible user experience.

Resources
Design templates
QuickChat_AI_Template.zip Contains:
QuickChat_ConsolePC_Templates.ai
Text-to -speech narration menu guidelines
Speech interactions
Speech synthesis API (Windows)
PlayFab Party text-to -speech and speech-to -text UX series
Part 1: PlayFab Party text-to-speech and text input UX Guidance
Part 2: PlayFab Party speech-to-text and text display UX Guidance
SDK documentation
"Accessible in-game chat overview" in the PlayFab SDK (see SDK Downloads)
Accessibility guidance
Griffiths, Gareth. Subtitles: Increasing Game Accessibility, Comprehension Gamasutra
Game Accessibility Guidelines A straightforward reference for inclusive game design
Straub, Josh. Game Accessibility: What It Is And Why It Matters Game Informer
Inclusive design
Xbox's Gaming for Everyone Initiative
Inclusive Design Microsoft Design Toolkit and education
Kojouharov, Stefan. 10 Tips on Creating an Addictive ChatBot Referenced in this document for conversational
UI tips.
PlayFab Party speech-to-text and text display UX
guidelines
5/24/2022 • 13 minutes to read • Edit Online

The PlayFab Party library gives game creators the power to engage more players through accessible game chat
options. It provides a means for voice chat to be transcribed to text and for text input to be converted to
synthesized voice. You can implement a custom UI solution for these features in your title. On Xbox and
Windows, you can use platform APIs to implement the relevant UI.
This document is part two of a two-part series covering UX solutions for speech-to-text and text-to-speech
implementation. Part one focuses on text-to-speech implementation, requirements, and console and PC UI
solutions, while this topic focuses on speech-to-text implementation, requirements, and console and PC UI
solutions.

Text-to-speech and speech-to-text scenarios


The following chart guides you through scenarios that players will experience when you enable speech-to-text
and text-to-speech features. It outlines user impact for three stages of the gaming experience: initial setup,
playing a game, and engaging in game chat.

EXP ERIEN C E STA GE SET UP P L AY C H AT M ESSA GE

Goal User enables User enters a User sends User receives


setting multiplayer game communication communication

Action Speech-to-Text Launches game User speaks User reads team's


voice replies
Alternative for Enters MP lobby converted to text in a
hearing voice replies speech-to-text chat
Overlay opens when overlay
game chat is initiated

Text-to-speech Launches game User types replies User hears team


using platform member's voice
Alternative for Enters MP lobby supported input replies
speaking voice replies methods
Game displays
method for text input Typed messages are
(keyboard, input field, converted to
etc) synthesized voice

UI Narration (in- User is guided by the For text messaging For text messaging
game) Xbox OS synthesized systems: Games use systems: Games use
voice to launch game the Speech synthesis the Speech Synthesis
Alternative for API to guide the user API to narrate replies
reading in-game Game uses the to launch the Xbox
menus and text Speech Synthesis API OS keyboard
replies to narrate menu
options leading the
user to the MP lobby
EXP ERIEN C E STA GE SET UP P L AY C H AT M ESSA GE

Narrator (Xbox OS) User is guided by the For text messaging N/A
Xbox OS synthesized systems: A virtual
Alternative for voice to launch game Keyboard is narrated
reading Xbox menus as the user types a
message

Understanding the API


Speech-to -text
Enabling transcription
Transcription of incoming audio for the user associated with a local chat control can be enabled by calling
PartyLocalChatControl::SetTranscriptionOptions() . When the operation completes, a
PartySetTranscriptionOptionsCompletedStateChange will be provided by
PartyManager::StartProcessingStateChanges() indicating whether the asynchronous operation succeeded.

Receiving transcriptions
When audio is sent to a chat control associated with a local user that has enabled transcription, the audio will be
transcribed. Each transcription will be indicated by a PartyVoiceChatTranscriptionReceivedStateChange provided
by PartyManager::StartProcessingStateChanges() . The speaker, receiver(s), and transcription text will be specified
in the state change. Additionally, the state change will specify whether the transcription text is a Hypothesis or
Final phrase. A Hypothesis phrase is a snapshot in the transcription process that indicates an iterative
refinement of the transcription text. These can optionally be used to improve the perceived responsiveness of
the transcription process. A Final phrase represents the end of the transcription process after a user has
completed a sentence or phrase.
Displaying transcriptions
When transcription text is received, it should be displayed according to the following UX design guidelines. The
Windows::Gaming::UI::GameChatOverlay or Windows::Xbox::UI::Accessibility API can be used on Windows or
Xbox, respectively, to use the default system text chat UI that has been designed to comply with these guidelines.

Discovery
For Xbox and Windows, users can find text-to-speech and speech-to-text settings in the Accessibility section
under Settings in Xbox Home (Xbox console) or Xbox App (Windows 10). The settings are controlled via toggle
buttons that enable or disable the features for all Xbox games specific to the user profile that integrate with the
platform settings. For all other platforms, refer to their accessibility guidelines for text-to-speech and speech-to-
text setting locations.

NOTE
If your game chooses to add additional settings that are game specific only, then they should be placed inside your game.
In general, accessibility options belong under the game’s settings/options menu. Ideally, settings should be available as a
dedicated button press and accessible from any screen or, at least, the Pause menu.

UX guidance for creating a custom conversation window


General best practices
Subtitles and voice chat transcription tackle a similar challenge: display rapid-fire, conversational text, overlaying
rich media. Documentation on subtitles can apply to a conversation window.
Basics
1. High contrast between text and background.
2. Avoid presenting too much text on-screen at one time.
3. Use a large enough text size for the screen size.
Good practices
1. Ensure users can find and enable text-to-speech settings before engaging in game chat.
2. Avoid clashes with other UI elements.
3. When stacking multiple replies, add newest strings at the bottom.
4. Distinguish between speakers.
5. Use a clear, readable font.
6. Allow the conversation window and content to be customized by the user.
Window size
To ensure an equivalent experience for all of your gamers, its crucial to consider both user needs and game UI
needs.
This section will walk through a method for determining the best display, based on:
The user's chat behavior.
Varying UI layouts using game chat (lobbies, game setup, game session).
Title-callable UI (TCUI) impact (for example, overlays, toasts, virtual keyboard).
Presentation requirements such as fonts and formatting.
Users' chat behavior
Different game features will drive varying chat density. For example - the game lobby during the game session,
and end-of-game wrap-up are times when game chat is engaged. However, the types of discussions change the
objectives of the screen. Knowing the type of discussion can help gauge whether a conversation window is
critical or optional to gameplay needs.
Discussion types
Small talk . Not critical for achieving objectives. For example, common interests, expletives, socializing.
Functional . Critical for achieving game objectives. For example, coordinating strategy with your team.
Chat length: minimum requirements
Discussion types in game chat influence a wide range of reply types by a single user (from short greetings and
confirmations to longer instructional and descriptive replies). Once you've determined a primary discussion type
for each screen, you can begin to make some broad assumptions about the type and length of replies.
Researching game chat activity for your game will deliver the most accurate results. It requires identifying
common patterns in multiple user conversations. One solution is to conduct a user-research test, using the
speech-to-text functionality inside your game to capture the user-research data of participants. Another
suggestion is to watch game streams of similar genres and track conversation patterns.
That data can then be applied to this simple strategy for determining conversation length:
Reply frequency - Determine how many replies were exchanged before a lull, and then average those
replies to arrive at a final number. Example: Two players chatting averaged five replies before a lull
occurred.
Reply length - Determine the average word and character count of a single reply. Example: A single
reply averaged 10 words and 35 characters (with spaces) per reply.
Formatting - Each chat-related state change includes useful information to help visualize it. The lengths
of each field need to be taken into account when determining formatting. In the following example, the
message type , i.e. whether the message is a result of speech-to-text or text message, can be inferred
from the state change type. A PartyVoiceChatTranscriptionReceivedStateChange will always indicate text
that is a result of voice input, and a PartyChatTextReceivedStateChange will always indicate text that is a
result of text input. The reply origin , i.e. who sent the communication, and the reply itself can be
determined by the fields within each state change.
Font size and type
Choosing a legible font is important for players who are reading any on-screen text UI, some of whom might
have low vision.

NOTE
Verdana is the most legible font that Microsoft ships. Even better than Verdana by itself is to present the font with high
contrast (full black on full white or vice-versa) and at large sizes. Size, contrast, and letterform are the three biggest factors
in legibility (in that priority order).

Example: Different typefaces of the same size can vary in readability.


A minimum of 28px for 1080p UI text (14sp) is recommended for chat transcriptions presented in a 10'
experience. Like subtitles, these are displayed for a limited duration and so the text should be notably larger than
the minimum acceptable (24pt for 10') for the rest of the UI.
Calculating your final minimum-size requirements
Now that you have your average reply frequency, reply length, formatting considerations, and font size and type,
you can determine your window size requirement:
Example: The result of using the specs above inside a window size of 525px (w) x 395px (h) .

Start testing your design by using the ConversationWindow_Template.ai . Go to Resources for the native
Adobe Illustrator (.ai) file.
Position and proportion
Now that you have minimum text requirements for the conversation window, you can begin testing positioning
and size ratio.
Positioning: relative vs. fixed
Aligning the conversation window to a grid format provides a very straightforward set of inputs that can scale
regardless of the screen resolution. For example, the Xbox OS speech-to-text UI references nine quadrants
(Left/Top, Left/Center, Left/Bottom, Middle/Top, and so on) for positioning.
If your game outputs to multiple screen resolutions (4K, PC), you won't have to worry about scaling 1080p X,Y
pixel values to a different screen size.
By having a predetermined number of relative positions, you won't have to fight with legacy code to maintain
pixel-perfect positioning of design elements, fonts or safe areas. Your design guarantees a relative position
instead.
Consider referencing multiple positions to accommodate varying screen complexity:
Identify screens where game chat activity is critical.
Avoid inhibiting interaction. (See Note)
Avoid hiding critical details. (See Note)
NOTE
Take care to position the conversation window so that it doesn't inhibit game activity. This will ensure speech-to-text users
can enjoy a comparable experience as other users.

User-controlled customization
There may be screens where there simply isn't room to accommodate a conversation window of any size.
Example: The end-of-game results UI fills the entire screen. A conversation window risks covering critical stats.

Solutions for game UI and conversation window conflicts


1. The user should be able to disable the feature via the OS .
Ideally, the user has the option to leave the game and turn the speech-to-text option on or off, by using
the Ease-of-Access settings.
UI impact: NONE
UX impact: POOR
Example: Disabling the speech-to-text setting via OS Settings. (This shows a critical path for the Xbox One
console)

2. The game provides a method for users to minimize the window .


Having a speech-to-text setting to minimize or move the window offers added flexibility for the designer
and the user.
UI impact: MODERATE Requires adding a minimize/maximize chat window button to an in-
game settings menu. We recommend that this option appear only when speech-to-text is enabled.
UX impact: GOOD This is a 3-click solution where settings menus are surfaced in the game.
Example: Minimize/maximize speech-to-text window via in-game Options menu (Xbox Console/PC
critical path

Console example: Add a speech-to-text setting in the Pause menu.

PC example: Add a speech-to-text setting in the Pause menu.


Enabling users to minimize or maximize the conversation window puts the choice in their hands. The
game doesn't have to try to avoid compromising critical real estate.
Game screens that do not require immediate responses give users time to shift focus away and edit their
settings. They can minimize or maximize the window without destroying the session. Keep navigation to
and from this setting as efficient as possible.
For game screens that do require immediate responses, or when point-and-click (PC) is not an option, a
button or key command can be directly mapped.
Console example: A button is mapped to toggle the display ON/OFF and is annotated in the legend.

PC example: A button is mapped to toggle the display ON/OFF and is annotated in the legend.
Functional requirements
Conversation continues to be tracked while the window is minimized.
The user can expand and see the latest replies. (The user does not see a history of missed replies.)
This option appears when a user profile's speech-to-text setting is detected as enabled.
This setting would not override the OS Profile's speech-to-text setting.
Display frequency
Chat activity will fluctuate between players during game sessions. There is no value to keeping an empty chat
window open when players aren't chatting.
Automatically close the window when chat has been inactive for a set period.
Example: The speech-to-text window closes after 15s of inactivity. This number is based on the time it would
take a user to read one message of 280 characters.

NOTE
It's worth testing various settings to ensure that opening and closing a window isn't too distracting on a game screen
with a lot of activity.
Scrolling
During ongoing conversations, the window must facilitate a view of most recent replies. Most recent replies are
displayed at the bottom of the replies and scroll up.

NOTE
Auto-scrolling is a solution that makes managing conversations easier for both developers and users. It comes closest to
mimicking fluid conversation. The less effort a user has to make to manage the view, the more time they have to focus on
gameplay. A manual scrollbar would require shifting controller focus, which can be disruptive during active gameplay.

Visual disparity
It may be tempting to design this chat window to match your UI style. However, the chat window has a specific
function, unique from other game components. It is presenting information that originates outside of game
instruction.
It is game information that also uses text and frames. A user could confuse the intention of the chat window with
actual in-game components, if they look too similar. Therefore, the Chat overlay must possess unique attributes
that clearly separate it from the game UI. Degree of disparity is up to the designer’s discretion.
Closing or destroying the conversation window
A game must determine when the conversation window remains active (while a user is multi-tasking) or when it
should close (for example, when a user exits a chat session). Keep in mind that this window represents a live chat
conversation and is not to be confused with instant messaging (IM). For example, if a user walks away from their
console or pauses a game, the conversation will continue but they'll have missed replies that occurred before
they return.

NOTE
UX recommendation: Keep the window active when a game is constrained or paused. Close the window when the game
exits.

Title-callable UI (TCUI)
Console example: The Xbox One Guide is TCUI and has a transparent overlay that dims the screen.

It's common for a platform’s system UI to be the ‘top’ visible layer of any game or app UI. For example, the Xbox
One operating system-initiated UI (error messaging, a virtual keyboard, toasts, the Xbox One Guide, people
picker, and other elements) applies a full screen, semi-transparent, black overlay with their content window.
UX impact : Visibility of the conversation window will be obscured.

Conclusion
PlayFab Party text-to-speech and speech-to-text APIs are highly effective features for including a wider range of
users in a game and gaming conversations. The more gamers engage and develop relationships, the more likely
they are to continue playing. This guidance will help ensure the best possible user experience.

Resources
Design templates
PlayFab Parties_AI_Templates.zip Contains:
PlayFab Parties_9GridTemplate.ai
ConversationWindow_Template.ai
Text-to -speech narration menu guidelines
Speech interactions
Speech synthesis API (Windows)
PlayFab Party text-to -speech and speech-to -text UX series
Part 1: PlayFab Party text-to-speech and text input UX guidance
Part 2: PlayFab Party speech-to-text and text display UX guidance
SDK documentation
"Accessible in-game chat overview" in the PlayFab SDK (see SDK Downloads)
Accessibility guidance
Griffiths, Gareth. Subtitles: Increasing Game Accessibility, Comprehension Gamasutra
Game Accessibility Guidelines A straightforward reference for inclusive game design
Straub, Josh. Game Accessibility: What It Is And Why It Matters Game Informer
Inclusive design
Xbox's Gaming for Everyone Initiative
Inclusive Design Microsoft Design Toolkit and education
Kojouharov, Stefan. 10 Tips on Creating an Addictive ChatBot Referenced in this document for conversational
UI tips.
PlayFab Party chat permissions and muting
5/24/2022 • 2 minutes to read • Edit Online

Overview
PlayFab Party gives you fine-grained control over how your players can communicate with each other's. Rather
than specifying teams or channels, PlayFab Party requires that explicit permissions between each pair of chat
controls be defined. The chat permissions system allows you to control incoming and outgoing voice
communication as well as incoming text communication between any pair of chat controls.

Chat permissions
Communication between chat controls is disabled by default and it is up to the Game to set the right
PartyChatPermissionOptions between each pair of chat controls. Chat permissions should reflect the relationship
between each chat control as determined by the scenario you are trying to achieve. For example, in a team
versus team scenario, you might want to set the chat permissions to allow all types of communication between
members of the same team, block audio communication between members of opposing team, and allow
receiving text between everyone in the session.
The following example shows how to enable all communication between a local and a remote chat control. The
variable localChatControlA is pointing to a valid PartyLocalChatControl object while remoteChatControlB is
pointing to a valid PartyChatControl object representing a chat control on a remote device.

PartyChatPermissionOptions allOptions = PartyChatPermissionOptions::SendAudio |


PartyChatPermissionOptions::ReceiveAudio | PartyChatPermissionOptions::ReceiveText;
localChatControlA->SetPermissions(remoteChatControlB, allOptions);

NOTE
Please note that chat permissions only apply locally. In the previous example, full bi-directional communication will only
happen if remoteChatControlB is remotely configured to allow all communication with localChatControlA

Muting
Games also have the ability to mute outgoing audio ( PartyLocalChatControl::SetAudioInputMuted() ) as well as
incoming audio from remote chat control ( PartyLocalChatControl::SetIncomingAudioInputMuted() ). The states of
these mutes can be accessed through their respective getters and are also reflected through the chat indicators
returned by PartyLocalChatControl::GetChatIndicator() and PartyLocalChatControl::GetLocalChatIndicator() .
Mutes are particularly useful to give some form of temporary control to the player without having to change
any of the chat permissions you might have set at the beginning of the gaming session.

How to configure popular scenarios


Push-to -talk
Push-to-talk should be implemented using local muting. Call PartyLocalChatControl::SetAudioInputMuted(false)
to allow speech and PartyLocalChatControl::SetAudioInputMuted(true) to restrict it.
Teams
Suppose that we have 4 users, A, B, C, and D, each on their own separate device. User A and User B are on team
Blue, and User C and User D are on team Red.
On User A's device:

// Enable all communication with teammate B


localChatControlA->SetPermissions(chatControlB, PartyChatPermissionOptions::SendAudio |
PartyChatPermissionOptions::ReceiveAudio | PartyChatPermissionOptions::ReceiveText);

// Disable all communication with opponents


localChatControlA->SetPermissions(chatControlC, PartyChatPermissionOptions::None);
localChatControlA->SetPermissions(chatControlD, PartyChatPermissionOptions::None);

Broadcast
Suppose that User A is the leader giving orders and User B, C, and D can only listen.
On User A's device:

localChatControlA->SetPermissions(chatControlB, PartyChatPermissionOptions::SendAudio);
localChatControlA->SetPermissions(chatControlC, PartyChatPermissionOptions::SendAudio);
localChatControlA->SetPermissions(chatControlD, PartyChatPermissionOptions::SendAudio);

On User B's device:

localChatControlB->SetPermissions(chatControlA, PartyChatPermissionOptions::ReceiveAudio |
PartyChatPermissionOptions::ReceiveText);
localChatControlB->SetPermissions(chatControlC, PartyChatPermissionOptions::None);
localChatControlB->SetPermissions(chatControlD, PartyChatPermissionOptions::None);

On User C's device:

localChatControlC->SetPermissions(chatControlA, PartyChatPermissionOptions::ReceiveAudio |
PartyChatPermissionOptions::ReceiveText);
localChatControlC->SetPermissions(chatControlB, PartyChatPermissionOptions::None);
localChatControlC->SetPermissions(chatControlD, PartyChatPermissionOptions::None);

On User D's device:

localChatControlD->SetPermissions(chatControlA, PartyChatPermissionOptions::ReceiveAudio |
PartyChatPermissionOptions::ReceiveText);
localChatControlD->SetPermissions(chatControlB, PartyChatPermissionOptions::None);
localChatControlD->SetPermissions(chatControlC, PartyChatPermissionOptions::None);
Using real-time audio manipulation to apply custom
voice effects
5/24/2022 • 8 minutes to read • Edit Online

PlayFab Party is a real-time networking and voice chat solution. When configured for voice chat, PlayFab Party
transmits microphone audio and plays it back unmodified. Some games need access to the voice chat audio
buffers to implement custom audio effects, such as spatial audio or voice filters. This document provides a
walkthrough of how to use the real-time audio manipulation feature to intercept and modify voice chat audio in
PlayFab Party.

Prerequisites
This walkthrough assumes you have basic familiarity with voice chat in PlayFab Party.

Platform support
Real-time audio manipulation isn't available on all platforms. While the methods associated with real-time audio
manipulation are present in the unified, cross-platform header, they're currently only implemented for Windows
and Xbox. The methods will return errors on other platforms.

Audio streams
Real-time audio manipulation introduces the concept of audio streams for retrieving audio from or submitting
audio to the library. There are two types of audio streams. The first is the source stream . A source stream is
used to retrieve audio from a chat control. Each chat control can only have a single source stream, called the
voice stream . For a local chat control, this is used to retrieve the microphone input; for a remote chat control,
this is used to retrieve incoming voice audio. If the voice stream exists for a chat control, the library will redirect
source audio for that chat control to its voice stream rather than handling the audio automatically. For a local
chat control, this means redirecting microphone audio to the voice stream instead of automatically encoding
and transmitting it; for a remote chat control, this means redirecting incoming voice audio to the voice stream
instead of automatically submitting it to each local chat control to be played back. Source streams are
represented by the PartyAudioManipulationSourceStream .
The second type of stream is the sink stream . A sink stream is used to submit audio to a chat control. Only
local chat controls can have sink streams, and they each can have two. They're called the capture stream and
render stream . If the capture stream exists for a chat control, the library will pull audio from the capture
stream to encode and transmit to other chat controls instead of the microphone. If the render stream exists for a
chat control, the library will pull audio from the render stream and play it back in addition to the voice chat
audio that is automatically played back from remote chat controls. Audio submitted to the capture stream is
used as the local chat control's microphone input; audio submitted to the render stream is played back or
"rendered" to the local chat control's audio output device. Sink streams are represented by the
PartyAudioManipulationSinkStream .

Configuring audio streams


By default, the library handles audio retrieval, transport, and playback. Therefore, chat controls are created
without any audio streams. You can create one or more streams for a chat control via the stream configuration
methods - PartyLocalChatControl::ConfigureAudioManipulationCaptureStream() ,
PartyLocalChatControl::ConfigureAudioManipulationRenderStream() , and
PartyChatControl::ConfigureAudioManipulationVoiceStream() . Once configured, a stream can subsequently be
retrieved via PartyLocalChatControl::GetAudioManipulationCaptureStream() ,
PartyLocalChatControl::GetAudioManipulationRenderStream() , and
PartyChatControl::GetAudioManipulationVoiceStream()

Each stream configuration method allows you to specify the format of the audio that you will retrieve from or
submit to the stream. For more information about supported formats, see the reference documentation for each
stream configuration method.
Retrieving audio from a source stream
You can retrieve audio from a source stream via PartyAudioManipulationSourceStream::GetNextBuffer() . When
voice activity is detected, a new buffer will be available approximately every 40 ms. If no buffers are available,
the call will succeed and provide a zero length buffer. The total number of buffers instantaneously available can
be retrieved via PartyAudioManipulationSourceStream::GetAvailableBufferCount() .
For efficiency, GetNextBuffer() provides a buffer that points to the library's memory instead of copying the
entire buffer. It can optionally be modified in place. Once you're done processing a buffer, you should release it
via PartyAudioManipulationSourceStream::ReturnBuffer() so that the library can reclaim its memory. Multiple
buffers can be retrieved before any are returned, and buffers don't need to be returned in the order they were
retrieved.
Submit audio to a sink stream
You can submit audio to a sink stream via PartyAudioManipulationSinkStream::SubmitBuffer() . The buffer is
copied by the library and can be immediately freed after the call completes.
Every 40 ms, the library consumes 40 ms of audio that has been submitted to the sink stream. To prevent audio
hiccups, audio should be submitted at a constant rate.

Scenarios
Microphone audio manipulation a.k.a. pre -encode buffer manipulation
Microphone audio manipulation is the act of intercepting and changing the microphone audio before it's
transmitted to other chat controls. This is sometimes called "pre-encode buffer manipulation" because the
microphone audio is modified before it's encoded and transmitted to other chat controls. If you wish to
implement this scenario for a local chat control, first configure a voice stream and capture stream for the local
chat control. Once configured, a function called by each tick of a dedicated audio thread to process the
microphone audio of that single chat control might look like the following.
// An app-defined function that takes a microphone buffer and generates a new
// buffer that should be transmitted to other chat controls.
std::vector<uint8_t>
ProcessLocalVoiceBuffer(
PartyMutableDataBuffer* inputBuffer
);

void
ProcessLocalMicrophoneAudioForSingleChatControl(
PartyLocalChatControl* chatControl
)
{
// Get the voice stream from which we want to retrieve audio. This provides
// the audio generated by the chat control's input device.
PartyAudioManipulationSourceStream* voiceStream;
RETURN_VOID_IF_FAILED(chatControl->GetAudioManipulationVoiceStream(&voiceStream));

// Get the capture stream to which we want to submit audio. This is used to
// submit audio that will be transmitted to other chat controls.
PartyAudioManipulationSinkStream* captureStream;
RETURN_VOID_IF_FAILED(chatControl->GetAudioManipulationCaptureStream(&captureStream));

// Get the next audio buffer from the voice stream.


PartyMutableDataBuffer buffer;
RETURN_VOID_IF_FAILED(voiceStream->GetNextBuffer(&buffer));

// If we retrieved a buffer, process it.


if (buffer.bufferByteCount > 0)
{
// Use the buffer we retrieved to generate a new buffer that will be
// treated as the "real" capture input and transmitted to other chat
// controls.
std::vector<uint8_t> processedBuffer = ProcessLocalVoiceBuffer(&buffer);

// Convert the buffer to a Party type.


PartyDataBuffer partyBuffer;
partyBuffer.bufferByteCount = static_cast<uint32_t>(processedBuffer.size());
partyBuffer.buffer = processedBuffer.data();

// Submit the processed buffer to the capture stream.


PartyError error = captureStream->SubmitBuffer(&partyBuffer);
if (PARTY_FAILED(error))
{
printf("Failedtosubmitbuffertosinkstream!error=0x%08x", error);
}

// Return the original buffer back to the voice stream.


error = voiceStream->ReturnBuffer(buffer.buffer);
if (PARTY_FAILED(error))
{
printf("Failedtoreturnbuffertosourcestream!error=0x%08x", error);
}
}
}

Remote audio manipulation a.k.a. post-decode buffer manipulation


Remote audio manipulation is the act of intercepting and changing incoming audio before it's rendered to each
local chat control. This is sometimes called "post-decode buffer manipulation" because the incoming audio is
modified after it's decoded but before it's rendered. If you wish to implement this scenario, first configure the
voice stream for each remote chat control and the render stream for each local chat control. Then, each tick of
your audio thread should pull audio from each voice stream, mix the audio into a single stream while optionally
applying effects, and submit the mixed buffer to each render stream. Depending on your game scenario, you
might need to mix the buffers into different streams for each local chat control. A function called by each tick of
a dedicated audio thread to process the incoming voice audio might look like the following.
// This is an app-defined function that takes a local chat control and list of remote voice buffers and
generates
// a single mixed buffer to submit to the local chat control's audio output.
std::vector<uint8_t>
GetOutputMixBuffer(
PartyLocalChatControl& localChatControl,
const std::map<PartyAudioManipulationSourceStream*, PartyMutableDataBuffer>& remoteVoiceBuffers
);

void
ProcessRemoteVoiceAudio(
const std::vector<PartyChatControl*>& remoteChatControls,
const std::vector<PartyLocalChatControl*>& localChatControls
)
{
std::map<PartyAudioManipulationSourceStream*, PartyMutableDataBuffer> remoteVoiceBuffers;

//Acquirevoicebuffersfromeachremotechatcontrol.
for (auto remoteChatControl : remoteChatControls)
{
// Get the voice stream for this chat control from which we will retrieve audio.
PartyAudioManipulationSourceStream* voiceStream;
PartyError error = remoteChatControl->GetAudioManipulationVoiceStream(&voiceStream);
if (PARTY_FAILED(error))
{
printf("Failedtogetvoicestream!error=0x%08x", error);
continue;
}

// Get the next audio buffer from the voice stream.


PartyMutableDataBuffer buffer;
error = voiceStream->GetNextBuffer(&buffer);
if (PARTY_FAILED(error))
{
printf("Failedtogetnextbuffer!error=0x%08x", error);
continue;
}

// If we retrieved a buffer, cache it in the map for mixing.


if (buffer.bufferByteCount > 0)
{
remoteVoiceBuffers[voiceStream] = buffer;
}
}

// If we didn't acquire any source buffers, we don't have anything to mix.


if (remoteVoiceBuffers.empty())
{
return;
}

// Mixthevoicebuffersandsubmittoeachrenderstream.
for (auto localChatControl : localChatControls)
{
// Get the render stream for this chat control to which we will submit audio.
PartyAudioManipulationSinkStream* renderStream;
PartyError error = localChatControl->GetAudioManipulationRenderStream(&renderStream);
if (PARTY_FAILED(error))
{
printf("Failedtogetrenderstream!error=0x%08x", error);
continue;
}

//Mix the buffers the buffers to generate a new, mixed buffer.


std::vector<uint8_t> mixedBuffer = GetOutputMixBuffer(*localChatControl, remoteVoiceBuffers);

// Convert the buffer to a party type.


PartyDataBuffer partyBuffer;
partyBuffer.bufferByteCount = static_cast<uint32_t>(mixedBuffer.size());
partyBuffer.buffer = mixedBuffer.data();

// Submit the mixed buffer to the render stream.


error = renderStream->SubmitBuffer(&partyBuffer);
if (PARTY_FAILED(error))
{
printf("Failedtosubmitbuffertorender stream!error=0x%08x", error);
}
}

//Releasethevoicebuffers.
for (auto voiceBuffer : remoteVoiceBuffers)
{
// Return the voice buffer that we had cached from this voice stream.
PartyError error = voiceBuffer.first->ReturnBuffer(voiceBuffer.second.buffer);
if (PARTY_FAILED(error))
{
printf("Failedtoreturnbuffer!error=0x%08x", error);
}
}
}

Privacy and mixing considerations


The library will provide audio through a remote chat control's voice stream as long as the remote chat control is
generating audio and chat permission and mute configurations allow the audio to be played back by at least one
local chat control. If the audio should be played for one local chat control but not another, you must omit it from
the audio mix for the latter chat control.
Chat indicator considerations
Configuring a voice stream for a remote chat control won't impact its chat indicator. You may need to implement
logic to reconciliate differences between the chat indicator and your mixing logic to choose the right UI indicator.
For instance, the chat indicator may indicate that the chat control is talking but custom mixing logic may choose
to drop the audio.
Mixed scenarios
In some scenarios, you might want to enable audio manipulation for some chat controls but not others. For
instance, maybe you want to apply effects to opposition players encountered during a game match but not to
players on the same team. In such a scenario, you can follow the steps previously outlined for remote audio
manipulation while only configuring a voice stream for the chat controls to which you want to apply audio
effects. The audio of the remaining remote chat controls will automatically be rendered to the local chat controls,
as long as mute and permission configurations allow it.
Troubleshooting Voice Chat
5/24/2022 • 3 minutes to read • Edit Online

If two players are trying to chat together and one or both of them can't hear each other, try these
troubleshooting steps.

Check the chat indicators


PlayFab Party's chat indicators can be used to troubleshoot audio problems.
Use PartyLocalChatControl::GetLocalChatIndicator() to inspect the instantaneous audio state of the local chat
control. A healthy chat control should return either PartyLocalChatControlChatIndicator::Silent or
PartyLocalChatControlChatIndicator::Talking depending on whether the library is detecting voice from the
microphone input.
If PartyLocalChatControlChatIndicator::AudioInputMuted is returned, the chat control's outbound audio
stream was previously muted via a call to PartyLocalChatControl::SetAudioInputMuted(true) and the mute
must be disabled by calling PartyLocalChatControl::SetAudioInputMuted(false)
If PartyLocalChatControlChatIndicator::NoAudioInput is returned, either the local chat control's audio input
was never set by calling PartyLocalChatControl::SetAudioInputMuted() or the audio input failed to
initialize. Continue to the next section for tips on diagnosing audio input initialization failures.
Use PartyLocalChatControl::GetChatIndicator() to inspect the audio input state of a remote chat control, relative
to a local chat control.
If PartyChatControlChatIndicator::Silent is returned while you were expecting to hear audio this might
means that there is a problem with the remote audio device or that the chat permissions on the remote
device are not configured to send audio to this chat control. Continue to the following section if this
sounds like what you are experiencing.
If PartyChatControlChatIndicator::Talking is returned but you can't still hear any audio, there might be a
problem with the local audio output device. Continue to the next section to learn how to check if an audio
device is healthy.
If PartyChatControlChatIndicator::IncomingVoiceDisabled is returned, this means that the local chat
control has not had its chat permissions configured to allow audio from the remote chat control.
Continue to the chat permission section.
If PartyChatControlChatIndicator::IncomingCommunicationsMuted is returned, this means that incoming
audio has been muted via a previous call to PartyLocalChatControl::SetIncomingAudioMuted() . Call
PartyLocalChatControl::SetIncomingAudioMuted() to unmute the remote chat control.

Verify that the audio device is successfully initialized


Shortly after calling PartyLocalChatControl::SetAudioInput() or PartyLocalChatControl::SetAudioOutput() you
will receive a PartyLocalChatAudioInputChangedStateChange or a PartyLocalChatAudioOutputChangedStateChange .
Both of these state changes will contain information that may help you troubleshoot any issue related to audio
devices. These state changes contain a PartyAudioInputState field and a PartyAudioOutputState field that will
give you information on the state of the audio device. If the state of the audio device is anything other than
Initialized , this means that PlayFab Party was unable to use the desired audio device. The errorDetail field
on the state change can also be used to get further information on the situation. Call
PartyManager::GetErrorMessage() to get the human readable form of the error detail.

NOTE
By default, chat controls will not be associated with any audio device. Be sure to call
PartyLocalChatControl::SetAudioInput() and PartyLocalChatControl::SetAudioOutput() on all of your chat
controls.

Verify that the chat controls have the right chat permissions
Use PartyLocalChatControl::GetPermissions() to look up the PartyChatPermissionOptions between two chat
controls. For example, if a user Alice is unable to hear another user Bob, you will want to make sure that Alice
has the permission to receive audio from Bob and that Bob has the permission to send audio to Alice.
On Alice's device:

PartyChatPermissionOptions chatPermissions;
PartyError error = localChatControlAlice->GetPermissions(remoteChatControlBob, &chatPermissions);
if (PARTY_SUCCEEDED(error))
{
if (static_cast<bool>(chatPermissions & PartyChatPermissionOptions::ReceiveAudio))
{
printf("Alice can receive audio from Bob!");
}
}

On Bob's device:

PartyChatPermissionOptions chatPermissions;
PartyError error = localChatControlBob->GetPermissions(remoteChatControlAlice, &chatPermissions);
if (PARTY_SUCCEEDED(error))
{
if (static_cast<bool>(chatPermissions & PartyChatPermissionOptions::SendAudio))
{
printf("Bob can send audio to Alice!");
}
}

Check default device vs. default communication device in Windows


A frequent point of confusion for audio on Windows is around the concepts of default device and default
communications device. Windows supports both concepts, and they can be different devices. PlayFab Party, by
design, uses the default communications device in the Windows version of the library when
AudioDeviceSelectionType::SystemDefault is passed to PartyLocalChatControl::SetAudioInput or
PartyLocalChatControl::SetAudioOutput . Troubleshooting and testing should always be performed in relation to
the default communications device.
Using text moderation
5/24/2022 • 2 minutes to read • Edit Online

PlayFab Party offers a text moderation solution that is integrated with text chat. Text chat can be moderated in
real-time to filter out offensive language. This feature is backed by Azure's Content Moderator. For more
information, see Azure Content Moderator.

Language support
Text moderation is supported for more than 30 languages. However, you don't need to do anything to configure
a language selection for text moderation; the language of each text message is automatically detected by Azure.
For a complete list of supported languages which support auto-detection and profanity filtering, refer to Azure
Content Moderator's list of supported languages.

Enabling text moderation


Text moderation is configured per chat control. It is be enabled by calling
PartyLocalChatControl::SetTextChatOptions() with the PartyTextChatOptions::FilterOffensiveText option. Chat
controls that have moderation enabled will receive text chat with offensive words masked by asterisks. Since
moderation is enabled per chat control, you are able to create UI to allow users to set their own moderation
choice. Alternatively, you can enforce moderation for some or all users.
To disable moderation for a chat control, use the same function, passing in a PartyTextChatOptions option that
does not contain the FilterOffensiveText flag.
Sample code:

// Opt into moderation


myLocalChatControl->SetTextChatOptions(PartyTextChatOptions::FilterOffensiveText, nullptr);

// Opt out of moderation


myLocalChatControl->SetTextChatOptions(PartyTextChatOptions::None, nullptr);

Sending and receiving moderated text


All text sent to a chat control with moderation enabled will have moderation applied, regardless of the sender's
own moderation settings. Text messages received by a chat control with moderation enabled will have the
chatText field in PartyChatTextReceivedStateChange replaced with the moderated version.

Additional fields are present on the PartyChatTextReceivedStateChange to enable more complex scenarios, such
as giving users an option to view an unfiltered version of the text. Refer to the
PartyChatTextReceivedStateChange reference page for more information.
If moderating a text message fails, either due to a service error or because the text was deemed offensive by the
service without being able to identify specific terms, then the entire text message will be masked with asterisks.
You can determine if this has happened by looking at PartyChatTextReceivedOptions enum provided in the
options field of PartyChatTextReceivedStateChange .

Adjusting filtering levels


For English, the level of filtering that happens for a chat control can be adjusted by using the
PartyManager::SetOption function. The filtering levels available are Family-Friendly, Medium, and Mature. The
default level is Family-Friendly.
Sample code:

// Set the filter level to Mature


PartyTextChatFilterLevel filterLevel = PartyTextChatFilterLevel::Mature;
PartyOption option = PartyOption::TextChatFilterLevel;
PartyError error = PartyManager::SetOption(nullptr, option, &filterLevel);

See also
Understanding how PlayFab Party chat works
PartyLocalChatControl::SetTextChatOptions
PartyChatTextReceivedOptions
PlayFab Party invitations and the security model
5/24/2022 • 10 minutes to read • Edit Online

PlayFab Party is designed to provide a secure communication environment by default. This helps protect games
and players, but security restrictions can raise API usage questions for developers. This page introduces the
security features of PlayFab Party, primarily focusing on invitations and effective patterns for using them.
PlayFab Party uses industry-standard encryption and authentication for all communication (management data,
game data, and real-time communication). This includes all peer-to-peer transmissions and all transactions to
Azure services, whether they're web services (which use HTTPS) or the transparent cloud relay service (which
uses DTLS).
Limiting access to a network is a core part of protecting the integrity of the network. The ability to join a
network is gated by four things:
Knowledge of the network descriptor
Possession of a valid PlayFab title_player_account entity token
Knowledge of an invitation identifier
Presence of the PlayFab entity ID for the above token in the specified invitation, or the specified invitation
being an open invitation
Note that a given PlayFab Party network can have a maximum of 32 players.

Invitations
An invitation ( PartyInvitation ) is an object within a network that grants user access to the network. Invitations
can be created and revoked throughout the lifetime of a network. An invitation has a creator, a unique identifier,
a revocability setting, and an optional set of users specified as entity IDs. A network can have any number of
active invitations, including none. A network is always created with an initial invitation.

Invitation lifetime
An invitation is active from the time it is created until it is revoked.
Creation
There are two ways to create an invitation. The first way is by calling PartyManager::CreateNewNetwork() . Since an
invitation is required to join a network, one must exist when a network is created. This invitation is known as the
initial invitation, and it has some special properties described below. The second way is by calling
PartyNetwork::CreateInvitation() .

The creator of an invitation is the user which was specified when calling PartyNetwork::CreateInvitation() . The
initial invitation has no creator.
When an invitation is created (or when joining a network with an active initial invitation), a
PartyInvitationCreatedStateChange is generated.

IMPORTANT
The initial invitation does not implicitly allow the creator of a network to join. Unless an open invitation is being used, be
sure to include the creator's entity ID in the user list.
Enumeration
Enumerating active invitations is done using PartyNetwork::GetInvitations() . Only the invitations created on
the local device, along with the initial invitation if it is still active, can be enumerated.
Revocation
An invitation is revoked by calling PartyNetwork::RevokeInvitation() . Only the creator of an invitation may
revoke it, except for the initial invitation, which may be revoked by any user. Additionally, an invitation is
automatically revoked when the user that created it is removed from the network.
When an invitation is revoked, a PartyInvitationRevokedStateChange is generated on all devices that could see
the invitation.
Once the initial invitation is revoked, it cannot be created again. Its identifier may be reused for a new invitation,
but that new invitation will not have the special properties of the initial invitation.

IMPORTANT
Revoking an invitation has no effect on the devices and users that have already joined the network. To remove a user or
device from the network, use PartyNetwork::KickUser() or PartyNetwork::KickDevice() . Note that these methods
are not yet implemented.

Invitation configuration
The configuration of an invitation is specified during creation using the PartyInvitationConfiguration struct.
Identifiers
Each invitation has an identifier which uniquely identifies it within the network. If an identifier is not specified
when creating an invitation, Party will assign one. For calls to PartyManager::CreateNewNetwork() , the assigned
identifier is returned in an out parameter and also reported in PartyCreateNewNetworkCompletedStateChange when
network creation completes. For calls to PartyManager::CreateInvitation() , the assigned identifier can be
retrieved from the invitation out parameter or the invitation field in
PartyCreateInvitationCompletedStateChange when the invitation creation completes.

Although an invitation identifier must be unique, after an invitation is revoked, its identifier may be reused when
creating a new invitation.
Initial invitation and other invitations
Although there is only one type of invitation, the initial invitation created by the call to
PartyManager::CreateNewNetwork() is a bit different from invitations created later via
PartyNetwork::CreateInvitation() . The differences are summarized in the table below.

P RO P ERT Y IN IT IA L IN VITAT IO N OT H ER IN VITAT IO N S

Visibility All devices can see the initial invitation. Only the device that created the
As long as the initial invitation has not invitation will be able to see it. A non-
been revoked, it will be returned by initial invitation will only be returned
calls to by
PartyNetwork::GetInvitations() . PartyNetwork::GetInvitations() if
Upon joining a network, each device it was created on that device, and a
will receive a PartyInvitationCreatedStateChange
PartyInvitationCreatedStateChange will only be generated for it on the
for the initial invitation if it has not creating device.
been previously revoked.
P RO P ERT Y IN IT IA L IN VITAT IO N OT H ER IN VITAT IO N S

Revocability Anyone may revoke the initial Only the creator may revoke the
invitation. When explicitly specifying invitation. When creating the
the invitation configuration, invitation, revocability must be set to
revocability must be set to PartyInvitationRevocability::Creator
PartyInvitationRevocability::Anyone .
.

Lifetime The initial invitation is active until it is A non-initial invitation is active until it
explicitly revoked. are explicitly revoked, or until the user
which created it is removed from the
network. When the user is removed
from the network, all the invitations
they created are automatically
revoked.

Creator The initial invitation has no creator. The user specified when calling
PartyInvitation::GetCreatorEntityId() PartyNetwork::CreateInvitation is
will return null. the creator.
PartyInvitation::GetCreatorEntityId()
will return that user's entity ID.

Invitations (other than the initial invitation) are hidden from other devices for privacy reasons. See the friends
list usage pattern for an example of why this is important.
Users and open invitations
An invitation contains 0 or more users specified as title_player_account entity IDs. If an invitation contains
users, that invitation only grants access to join the network to those users. However, if an invitation contains no
users, this is an open invitation. Any user may join the network with the identifier of an open invitation.

NOTE
On a multi-user device, such as a game console, be sure to use the correct invitation with the correct user. Depending on
which users are specified in each invitation, it is possible that different users on the device might need to use different
invitations when authenticating a user into the network via PartyNetwork::AuthenticateLocalUser().

Immutability
Once an invitation is created, its configuration cannot be changed. However, after an invitation has been
revoked, another can be created with the same identifier but a different configuration. See the dynamic single
invitation usage pattern.

Usage patterns
PlayFab Party invitations are simple but flexible. There are many effective ways to use them to achieve different
access models for a network. Below are a few common patterns.
Open network
An open network is the simplest to understand and implement. It allows anyone with the network descriptor
and invitation identifier to join.
Create an open network by passing null for the initialInvitationConfiguration parameter when calling
PartyManager::CreateNewNetwork() . The identifier for the open invitation is returned as an out parameter. After
the network creation completes, share the network descriptor and invitation identifier to allow users to join.
Optionally, you may close the network at any point in the future by revoking the initial invitation.
WARNING
Because a network is only as secure as the devices and users that join it, exercise caution when sharing the network
descriptor and invitation identifier of an open network.

Static user list


For games that know all players in advance, such as a game created by matchmaking with no backfill, a static
user list is an easy and effective pattern. This allows only those users identified before the game begins to join
the network.
Create a PartyInvitationConfiguration struct and add the known users to its entityIds field. Pass this struct
into PartyManager::CreateNewNetwork() . After the network creation completes, share the network descriptor and
invitation identifier to allow users to join.
One -to -one invitations
In a game where users are individually invited by existing users, a one-to-one invitation pattern is effective and
simple.
Create a PartyInvitationConfiguration struct and add only the creator to its entityIds field. Pass this struct
into PartyManager::CreateNewNetwork() . Once the creator connects to the network, the initial invitation may
optionally be revoked. Alternatively, the creator of the network can create an open network and then revoke the
initial invitation as soon as they connect.
Create additional PartyInvitationConfiguration structs for each user that should join the network. Create
invitations by passing these structs into PartyNetwork::CreateInvitation() . Share the network descriptor with
each user along with the invitation identifier for their specific invitation. As users join, they may repeat this
pattern to invite more users.
Once a user joins, their specific invitation may optionally be revoked.
Friends list
For games which want to allow each user's friends to easily join without creating one-to-one invitations,
invitations containing the users' entire friends lists can be created.
After connecting to the network, each user will create a PartyInvitationConfiguration struct and add each of
their social platform friends to its entityIds field. Pass this struct to PartyNetwork::CreateInvitation() , and
share the network descriptor and invitation identifier with friends. When a user's friends list changes, the
invitation should be revoked and a new invitation created with the new friends list.
Dynamic single invitation
Many games will have a lobby or other external service which controls who should join a given network. To
keep a network in sync with the external service, a dynamic single invitation pattern can be used. This pattern
uses a single invitation with a well known identifier.
There are two variants of this pattern. Either the external service can select a single user to manage invitations
for the network, or it can ask all users to attempt to manage invitations. In both cases, whenever the set of users
which should be in the network changes, the external service notifies the user(s), and the user(s) attempt to
revoke the current invitation and create a new invitation with the same well known identifier containing the new
full set of users.
Single user management
Having a single user responsible for revoking the current invitation and creating the new invitation leads to
predictable ownership of the invitation. However, the external service will need to the following.
Select the user that will manage invitations.
Select a new user when the previous user leaves the network.
All user management
Having all users attempt to manage invitations leads to unpredictable invitation ownership, but prevents the
external service from needing to select a single user. Instead, a user on each device will do the following.
Attempt to revoke the current invitation. For the initial invitation, all users will attempt this but only one will
succeed. For other invitations, only the user who created the last invitation will be able to attempt to revoke
it, since the invitation will not be visible to the other users.
Attempt to create a new invitation. Since invitations must have unique identifiers, only one of the users will
succeed. That user must notify the others that it is the new invitation owner, since the invitation will not be
visible on other devices.
When the creator of the current invitation leaves the creating device, all users must again attempt to create a
new invitation, just like above.

IMPORTANT
When revoking an invitation and creating a new one with the same identifier, there will be a small window of time where
the invitation identifier is invalid. If you are using this approach, it will be necessary to retry the call to
PartyNetwork::AuthenticateLocalUser() if it fails after a reasonable waiting period.

Rolling open invitation


For games where a lobby or other external service controls who should join a given network, an alternative to
the dynamic single invitation pattern is the rolling open invitation pattern. In this pattern, there is always a single
open invitation. The invitation is revoked and re-created with a new identifier whenever a user that was
previously allowed to join is removed from the external service's user list. The invitation identifier acts like a
password, and should be similarly protected. The pattern can be implemented in these steps:
The external service selects a device to create the network and specifies the invitation identifier to use.
The external service sends the invitation identifier to all other users that should join the network.
When a new user should join the network, the external service shares the current invitation identifier with
that user.
When an user that had been given the current invitation should no longer be allowed to join, the external
service will need to "change the password" by doing the following.
Select a new invitation identifier.
Request that one or all of the users revoke the current invitation and create a new one with the
selected invitation identifier. See dynamic single invitation for a discussion of single user management
versus all user management.
Share the new invitation identifier with all users that should now be allowed to join the network.

Next steps
Learn how PlayFab Party interacts with your discovery flows
Integrating discovery with PlayFab Party
5/24/2022 • 4 minutes to read • Edit Online

Discovery is the process by which users find each other to play together. PlayFab Party does not provide a
discovery mechanism, but can be used with any existing mechanism which provides communication between
users.

Basic creation and join flow


A PlayFab Party network is created by a user on a single client, advertised, and then joined by other users on
different clients.
Creating a network
The first consideration when using a PlayFab Party network with a game session is choosing which client and
user will create the network ( PartyManager::CreateNewNetwork() ). From the perspective of PlayFab Party, it
doesn't matter which user does this; any user can create a network. The creator is given no special privileges
within the network. However, the client which creates the network is responsible for:
setting immutable network configuration ( PartyNetworkConfiguration )
determining the initial invitation ( PartyInvitationConfiguration )
advertising the network to other users
The initial invitation contains an identifier and a list of users that are allowed to join the network. The users are
specified as a list of title_player_account Entity IDs. Alternatively, the list can be empty, allowing any user with
network descriptor and invitation identifier to join.
Advertising a Network
In order to join to an existing PlayFab Party Network, a client needs two pieces of information:
network descriptor
invitation identifier
A PlayFab Party network is identified by a network descriptor ( PartyNetworkDescriptor ). This is a mostly opaque
structure which encodes information required to establish a connection to the network. The network descriptor
is provided to the creating client after network creation has completed (
PartyCreateNewNetworkCompletedStateChange , PartyNetwork::GetNetworkDescriptor() ). To ease development,
PlayFab Party provides methods for serializing and deserializing the network descriptor to and from a web-
friendly string ( PartyManager::SerializeNetworkDescriptor(), PartyManager::DeserializeNetworkDescriptor() ).
An invitation identifier is a string which uniquely identifies an invitation. It is provided by a client when creating
an invitation explicitly or when creating the initial invitation while creating the network. If the client does not
supply an invitation identifier, one will be uniquely generated.
To advertise the new network to other users, send these two pieces of information via any appropriate
communication medium.
Joining a network
Joining a network it is a two-step process. A client that wishes to join a network must first connect to the
network by providing the deserialized network descriptor to PartyManager::ConnectToNetwork() , and then
authenticate a user by providing the invitation identifier to PartyNetwork::AuthenticateLocalUser() .
Scenario examples
Social invitations
The simplest scenario is one in which a single user creates a game session and wishes to invite other known
users via their shared social platform. The flow might look something like this:
The inviter creates the network with an open invitation, or an invitation containing all the users that the
inviter wants to play with.
Once the network is created, the inviter sends the network descriptor and the invitation identifier to the other
users via the social platform's invitation mechanism.
Each invited user uses the network descriptor and invitation identifier to connect to the network.

NOTE
When specifying users in an invitation, the users' title_player_account Entity IDs are used. These Entity IDs will need
to be obtained out-of-band of PlayFab Party.

Lobby
If your game provides a lobby which allows data to be sent between clients, it can be used as a communication
medium for exchanging network connection information. The flow might look something like this:
A set of users is selected to play a game together.
One of those users is selected as the creator.
Each user in the set sends their title_player_account Entity ID to the creator.
The creator creates the network, specifying the users' Entity IDs in the initial invitation configuration.
Once network creation completes, the creator sends the network descriptor and the initial invitation identifier
to the set of users that should join.
Each user uses the network descriptor and the invitation identifier to connect to the network.
Matchmaking
A matchmaking service, such as PlayFab Matchmaking, can be used to find a list of users to play with. The flow
might look something like this:
Users initiate a match request with the service. The title_player_account Entity ID must be part of the
request, because the match result must contain each user's Entity ID.
Users receive a match result containing the set of users that should be part of the network.
A predetermined algorithm is used to select which user will be the creator.
The creator creates the network, specifying the other matched users' Entity IDs in the initial invitation
configuration.
Once network creation completes, the creator uses an out-of-band communication medium to send the
network descriptor and the initial invitation identifier to other matched users.
Each matched user uses the network descriptor and the invitation identifier to connect to the network.

NOTE
An out-of-band communication medium is required to send the connection information from the creator to the other
matched users.
Configuring transport behavior
5/24/2022 • 2 minutes to read • Edit Online

PlayFab Party's networking capabilities expand on the User Datagram Protocol (UDP) features of the native
platform to provide datagram transport facilities that are ideal for real-time multiplayer games.
While Transmission Control Protocol (TCP) provides reliable streams, and UDP provides unreliable datagrams,
Party’s networking behavior can be configured on a per datagram basis. When using
PartyLocalEndpoint::SendMessage to transmit a datagram from a local Party endpoint to a remote endpoint you
can specify PartySendMessageOptions to fine-tune the desired transport behavior.
Capabilities include:
Guaranteed Deliver y - The GuaranteedDelivery flag ensures the message arrives at all targets, implicitly
retransmitting data if necessary to mitigate environmental packet loss. This option flag works well when
sending important state information that must always reach the destination or else the target should be
removed from the network. The default option is BestEffortDelivery which provides UDP-like fire and
forget behavior.
Sequential Deliver y - Orders the delivery of the message relative to other messages that were sent
sequentially from this local endpoint to the target endpoint. Use this option flag to send state information
that must reach the destination in a particular sequence. This may result in a slightly lower network efficiency
and possibly longer wait to receive all the packets when there is packet loss or reordering by the
environment. Using SequentialDelivery with GuaranteedDelivery may result in messages being queued on
the target endpoint while waiting for previously sent sequential messages to arrive. This may result in a
perceived increase in latency when experiencing environmental packet loss or reordering, but the target
endpoint will always see every message, in the same order in which they were sent. This performance trade-
off is common to TCP-like protocols and sometimes called head-of-line blocking.
Coalescing - The Party library automatically fragments and reassembles large messages that exceed the
maximum size supported by the environment so that callers are not required to manage this. But if you're
sending many small datagrams, coalescing multiple messages together in a single packet allows maximizing
bandwidth efficiency (reducing per-packet overhead) at the potential expense of perceived latency for a
message if you delay its transmission in order to coalesce. Sending with the CoalesceOpportunistically flag
(the default coalescence option) causes the Party library to coalesce the message with other queued
messages, if any are available, but not to wait for more messages if this message can be transmitted
immediately. Sending with the AlwaysCoalesceUntilFlushed flag causes the Party library to delay
transmission until PartyLocalEndpoint::FlushMessages is called, at which point the queued messages will be
coalesced and transmitted.
Network statistics and local queueing
Depending on the message sending options and network state, Party might locally queue messages before
transmission. This local queueing is carefully managed to avoid introducing latency. This is necessary to ensure
that Party does not flood the player's network and that features like coalescing can be applied.
PartyNetwork::GetNetworkStatistics allows you to collect data on aggregate network performance, including
latency to Party relay service. PartyLocalEndpoint::GetEndpointStatistics allows for visibility into queuing and
packet loss statistics for a specific remote endpoint.
PlayFab Party and direct peer-to-peer connections
5/24/2022 • 7 minutes to read • Edit Online

This page explains how you can enable and use direct peer-to-peer connections in PlayFab Party using example
game code. It also includes considerations to help you evaluate when to use direct peer-to-peer connections in
your games.

When to use direct peer-to-peer connections


PlayFab Party supports a wide variety of communication topologies. Conceptually, all chat or data messages are
from one peer device or user directly to others. However, Party will automatically leverage a transparent cloud
relay service to avoid common environmental and security problems with actually establishing direct peer-to-
peer connections. You can achieve low latency data transmission by leveraging its background quality of service
(QoS) measurements. (For more info, see PlayFab Party QoS measurements.) You can optionally enable direct
peer-to-peer connections to reduce data transmission latency further. Due to security concerns detailed under
"Security considerations" below, Microsoft recommends that you use our cloud relay service instead of enabling
direct peer-to-peer connection unless your title has strict latency requirements.
Platform support
Direct peer connectivity is supported in the Windows 10, Microsoft Game Core, Nintendo Switch, PlayStation 4,
and PlayStation 5 versions of the Party library. Other versions of the library will always use the cloud relay for
data transmission, regardless of the direct peer connectivity options specified through the client API.
Security considerations
Because direct peer connectivity are used to send data directly between clients, the clients all need to know how
to connect to one another. This is done by sharing client IP addresses between clients in a game session together.
For example, if a 16 player multiplayer game uses direct peer connectivity to update player positions, each of the
16 game clients needs to know the IP addresses of the 15 other clients to know who to send data to.
Sharing IP addresses between game clients is a security risk. Sharing IP addresses may allow bad actors to
detect the IP address and use it to maliciously attack other players outside of games. A common method to
carry out these attacks if through Denial-of-Service (DOS) attacks, or a variation called Distributed Denial of
Service (DDOS) attacks. The attacks work by attempting to overwhelm a network with superfluous network
traffic. If an attacker can send enough network traffic to their victim, the victim’s network hardware (modem and
router) has to spend all its time processing the superfluous traffic, and doesn't have any time to do its normal
jobs of processing legitimate networking connections. Effectively, this means that the victim can’t use their
network for the entire duration of the attack. This is frequently referred to as getting "booted offline."
In conclusion, successful direct peer connectivity may provide lower latency between some devices. However,
attempting to establish it also requires users to disclose their IP addresses to others, which may enable
malicious users to attack their devices and internet connections outside of the title. Direct peer connection also
may not be permitted on certain platforms for policy reasons. Be sure to use the appropriate direct peer
connectivity options for your performance and security goals. If you decide to use direct peer connectivity after
weighing the risks, please use the following examples to opt-in your title on a per-network and per-device basis.
LAN scenarios
Direct peer connectivity in Party can be used to enable extremely low latency in LAN scenarios. Even in these
scenarios, however, limited Internet connectivity is required to support user authentication, LiveOps data and
insights, and voice chat accessibility features.
Upstream bandwidth considerations
Using direct peer-to-peer connectivity may increase your game's upstream bandwidth usage. When transmitting
a game or voice message through the cloud relay service, Party sends a single message to the service; the
service then replicates and forwards the message to each target device. When transmitting a game or voice
message through direct peer-to-peer connections, Party replicates and sends the message through a direct
connection for each target device to which a direct peer-to-peer connection has been established. Therefore,
your game's upstream bandwidth usage will scale proportionally with the number of devices to which a direct
peer-to-peer connection has been established. Consider whether this increase in upstream bandwidth is
acceptable for your game before enabling direct peer-to-peer connections.

How to use direct peer-to-peer connections in your game


Enabling direct peer-to -peer connections in your network
When creating a network via PartyManager::CreateNewNetwork() , you can specify various network configuration
parameters through the PartyNetworkConfiguration provided to the call. You can use the
PartyNetworkConfiguration::directPeerConnectivityOptions field to specify whether and how direct peer-to-peer
connectivity is supported for devices in the network.
The following example shows a network configuration that specifies direct peer-to-peer connections should be
attempted among all devices in the network, regardless of platform type or login provider.

PartyNetworkConfiguration configuration = {};


configuration.directPeerConnectivityOptions = PartyDirectPeerConnectivityOptions::AnyPlatformType |
PartyDirectPeerConnectivityOptions::AnyEntityLoginProvider;
// Initialize the rest of the network configuration parameters appropriately for your game before using.

As part of successfully authenticating an initial user into a network, a device may attempt to establish direct
peer-to-peer connections with other devices already participating in the network when permitted by the
network configuration. For attempts that are successful, endpoint messages and chat data between the devices
will be transmitted using those direct connections. For attempts that fail due to environmental incompatibilities
between the devices, all communication between those devices will be transmitted via transparent cloud relay
servers instead. If the devices aren't permitted to attempt direct peer connections by the network configuration,
then they never exchange IP address information and will always transmit endpoint messages and chat data via
transparent cloud relay servers.

NOTE
Establishing direct peer connectivity is best effort and may not be possible due to environmental factors, per-device
connectivity options, or platform policy. For more information about evaluating whether a direct peer-to-peer connection
was established to a particular device, see Evaluating the connection type and latency.

Constraining direct peer connectivity per device


Besides the direct peer connectivity options in the network configuration, direct peer connectivity may be
further constrained by a device for all networks into which it authenticates by using PartyManager::SetOption()
to set PartyOption::LocalDeviceDirectPeerConnectivityOptionsMask . All flags are evaluated using a bitwise AND
operation. That is, a particular flag is actually only in effect for a given network's pair of devices if it's enabled in
three places: the network configuration, and both devices' respective local mask options. Even if the network
configuration permits direct peer connectivity of the relevant form, either device can independently opt out of
the IP address disclosure and direct connection attempts between them by not enabling the flag in its local
device mask option. In versions of the library that support direct peer connectivity, the
PartyOption::LocalDeviceDirectPeerConnectivityOptionsMask value defaults to permitting all direct peer
connections enabled by networks. Therefore, you only need to configure it if you have device-specific
requirements to prevent some or all direct peer connectivity involving the local device.
The following example shows how to constrain direct peer connectivity for the local device so that it will only
attempt to establish direct peer connectivity to devices of the same platform.

PartyDirectPeerConnectivityOptions localDeviceMask = PartyDirectPeerConnectivityOptions::SamePlatformType |


PartyDirectPeerConnectivityOptions::AnyEntityLoginProvider;
PartyError error = PartyManager::GetSingleton().SetOption(nullptr,
PartyOption::LocalDeviceDirectPeerConnectivityOptionsMask, &localDeviceMask);
if (PARTY_FAILED(error))
{
printf("Failed to set local device direct peer connectivity options mask! error = 0x%08x\n", error);
}

Evaluating the connection type and latency


You can determine whether the local device actually established a direct peer-to-peer connection to a specific
remote device by calling PartyNetwork::GetDeviceConnectionType() .
We recommend that you don't actively enforce the availability of a direct peer-to-peer connection for any given
pair of devices (i.e., don't call PartyNetwork::LeaveNetwork() if PartyNetwork::GetDeviceConnectionType() reports
a value other than PartyDeviceConnectionType::DirectPeerConnection ) since the specific underlying transmission
method in use doesn't alter the overall logical ability to communicate. If your game design has stringent
requirements for maximum message latency that encourage direct peer connectivity, it's better to take action on
the current concrete observations of that latency as reported by the
PartyEndpointStatistic::AverageDeviceRoundTripLatencyInMilliseconds statistic rather than make abstract
assumptions based on transmission mechanism. Otherwise you might continually hinder users trying to play
with the same set of friends who always need to use nearby transparent cloud relay servers due to
environmental factors beyond their control.
The following example shows how to inspect the round trip latency from a localEndpoint to a remoteEndpoint
in a network .
// A helper for inspecting the connection type and average round trip latency between a local endpoint and a
remote
// endpoint in a network.
void PrintConnectionTypeAndLatency(
PartyNetwork* network,
PartyLocalEndpoint* localEndpoint,
PartyEndpoint* remoteEndpoint
)
{
// Retrieve the device associated with the remote endpoint.
PartyDevice* remoteDevice;
PartyError error = remoteEndpoint->GetDevice(&remoteDevice);
if (PARTY_FAILED(error))
{
printf("Failed to get the remote device! error = 0x%08x\n", error);
return;
}

// Get the device connection type.


PartyDeviceConnectionType connectionType;
PartyError error = network->GetDeviceConnectionType(remoteDevice, &connectionType);
if (PARTY_FAILED(error))
{
printf("Failed to get device connection type! error = 0x%08x\n", error);
return;
}

// Retrieve the latency statistic.


PartyEndpointStatistic latencyStatistic =
PartyEndpointStatistic::AverageDeviceRoundTripLatencyInMilliseconds;
uint64_t latencyStatisticValue;
error = localEndpoint->GetEndpointStatistics(
1, // targetEndpointCount
&remoteEndpoint, // targetEndpoints
1, // statisticCount
&latencyStatistic, // statisticTypes
&latencyStatisticValue); // statisticValues
if (PARTY_FAILED(error))
{
printf("Failed to get latency statistic! error = 0x%08x\n", error);
return;
}

// Print the results.


printf("Local endpoint 0x%p and remote endpoint 0x%p in network 0x%p have average round trip latency
%llu ms and device connection type %i\n",
localEndpoint,
remoteEndpoint,
network,
latencyStatisticValue,
static_cast<int32_t>(connectionType));
}

Billing meters
The same billing meters are applied in networks that use direct peer-to-peer connections as in networks that use
the cloud relay service. However, only game or voice data that goes through the cloud relay service count
toward the Network egress and Par ty voice meters.
PlayFab Party port usage, firewall and packet size
requirements
5/24/2022 • 5 minutes to read • Edit Online

This topic provides details about Azure PlayFab Party port usage, firewall and packet size requirements that are
needed to enable chat and data communication.

Communication Patterns
Azure PlayFab Party has two communication patterns that must be permitted by the local device and
environmental infrastructure in order for API operation to succeed:
1. HTTPS communication, which is initiated from the API caller to multiple cloud web services, including
playfabapi.com.
2. UDP socket-based secure communication with transparent cloud relay servers, and other peer devices (if
supported).
If either pattern is blocked, early PlayFab Party API operations or automatic notifications such as the initial
PartyRegionsChangedStateChange will report PartyStateChangeResult::InternetConnectivityError .

For web service request issues, other necessary PlayFab and platform operations outside of Party such as the
user login functions would also likely fail. These failures are often caused by local firewall restrictions or proxy
requirements for HTTPS connections. Most issues can be resolved by enabling direct, outbound HTTPS
communication to cloud web services from the local device or network.

HTTPS Domain Names


Microsoft Azure PlayFab Party performs UDP and HTTPS connections to multiple cloud services. To ensure
correct functionality, environments that filter HTTPS traffic based on domain name need to ensure the following
names or name patterns are accessible:
HTTPS connectivity:
*.playfabapi.com
*.speech.microsoft.com
api.cognitive.microsofttranslator.com
This list of domain names can change without notice. Please ensure to check this list regularly and expect
changes.

MTU and packet sizes


Azure PlayFab Party automatically performs fragmentation and reassembly to fit large application messages
within environmental packet size limits. Some network environments can still cause communication failures
despite this functionality.
PlayFab Party currently expects environments to support a Maximum Transmission Unit (MTU) size of at least
1419 bytes to avoid poor performance or potential connectivity failures. This MTU size is supported in typical
environments. Virtual Private Networks (VPNs), IPv4/IPv6 tunneling, or explicit administrative configuration
might reduce the MTU size in one or both directions of the network path between the Party client, service, or
other clients.
If the MTU supported end-to-end in a given environment is insufficient, the PartyManager::ConnectToNetwork
operation may fail with PartyStateChangeResult::InternetConnectivityError . Alternatively, connectivity may
succeed but the device may encounter additional unnecessary latency, packet loss, or unexpected
disconnections.
Some platforms provide tools for end users, developers, or Internet Service Providers to help troubleshoot MTU
configuration in their environments that should be used if possible.

Local device UDP port usage


By default, the PlayFab Party library will bind its UDP socket to an available local port dynamically assigned by
the OS for most platforms. An exception is Microsoft Game Core where PlayFab Party will default to binding to
that platform’s "preferred local UDP multiplayer port".
Titles can alter this behavior to bind to a specific local port number or to an OS-selected available port other
than the Microsoft Game Core "preferred local UDP multiplayer port" by setting the
PartyOption::LocalUdpSocketBindAddress option prior to calling PartyManager::Initialize() . If the requested
port is already in use in your title or by another application on the device, either PartyManager::Initialize() will
report an error immediately, or the initial PartyRegionsChangedStateChange will report a
PartyStateChangeResult::FailedToBindToLocalUdpSocket error and asynchronous network creation or connection
operations will fail.
Titles are recommended to use the default local port selection behavior for maximum, configuration-free
compatibility unless specifically requested by the end user for an environment-specific reason. You may have
additional platform-specific requirements if your title uses non-default values. For example, the provided
application manifest excerpt in the Xbox XDK prerequisites assumes the title is using these defaults and that the
local device is therefore binding its PlayFabPartyUdpInitiatorToCloudService socket to port 0. You should consult
each platform’s documentation for guidance on port usage.
PlayFab Party communication always requires outbound-initiated packets and their subsequent replies to be
permitted from this selected local UDP port to remote destinations described in the next section. Network
administrators should follow Internet standard best practices for firewalls and Network Address Translation
(NAT) such as in RFC 4787 - "Network Address Translation (NAT) Behavioral Requirements for Unicast UDP" for
maximum compatibility. This is especially important for titles that are using direct peer-to-peer connections for a
Party network, since environments with only minimal support might allow connecting to the network but
prevent establishing that direct communication from one device to another.

Remote IP addresses and UDP ports


Microsoft Azure PlayFab Party provides dynamically-scaled services across multiple regions to offer the best
latency to users. This means there is no permanent remote destination hostname, IP address, or port that can be
referenced by network administrators interested in strict communication constraints.
Microsoft provides weekly updates of an IP address range list for Azure that is available for download. This list
can be useful if a continually-synchronized policy is feasible to restrict local network traffic. In most cases, the
ongoing maintenance of this list is a challenge and prone to subtle connectivity failures. Also, for direct peer-to-
peer connections within a Party network the remote client IP addresses also have to be known and enabled for
connectivity. For these reasons we recommend firewalls not restrict remote IP address connectivity.
The supported remote port range that may be in use by Azure PlayFab Party can be any ports other than the
Internet Assigned Numbers Authority (IANA) reserved range of 0-1023. Currently transparent cloud relays will
only be assigned port numbers from 30000 and above, but Microsoft reserves the right to change this behavior
in the future and policies constraining connectivity to this range are not recommended. As a best practice, the
port range of 1024-65535 should be used instead. This is particularly important for titles that are using direct
peer-to-peer connections for a Party network, since NAT implementations will typically assign ports from this
range. Blocking remote ports other than the full recommended range may also prevent direct communication.
To enable UDP connectivity, environments that filter UDP traffic based on domain name need to ensure the
following names or name patterns are accessible:
*.cloudapp.net
Filtering remote IP addresses for UDP connectivity via domain name resolution is possible but strongly
discouraged. Currently all connections to transparent cloud relay servers will resolve names of the form
*.cloudapp.net, but this pattern is subject to change without notice. Restricting UDP connectivity to only IP
addresses resolved by names will also prevent direct peer-to-peer connection.

See also
PlayFab Party and direct peer-to-peer connections
Multiple networks
5/24/2022 • 3 minutes to read • Edit Online

PlayFab Party supports using multiple PlayFab Party networks simultaneously. The following diagram provides
an example representation of how different objects might relate to each other in a multi-network scenario.

For a more complete explanation of how these relationships work, check out the documentation covering
PlayFab Party objects and their relationships.
This page will cover when using multiple networks is appropriate, when it isn't, and common pitfalls to avoid.

WARNING
Using multiple, simultaneous PlayFab Party networks is an advanced scenario that may require more complex game logic
to manage. Often, a game scenario which uses multiple networks can be redesigned or simplified to only require a single
network, and care should be taken to evaluate whether this is possible before designing your game's network architecture
around multiple Party networks. More information on when multiple networks is or is not appropriate can be found in the
next section, When to use multiple networks.

When to use multiple networks


PlayFab Party networks are designed to provide a real-time communication channel between a collection of
devices for exchanging game or chat data. Multiple networks often come into play when subsets of devices may
need to communicate for differing spans of time.
An example scenario for multiple networks is to manage "fire team chat" where a group of players (the fire
team) wants to maintain a constant, seamless chat session across multiple game sessions. For example:
Player A, Player B, and Player C want to play an online game together.
They each create a chat control, join a Party network together, and connect their chat controls to that network
enabling chat.
When they join a multiplayer game session with other players outside of their fire team, they join a separate
Party network and create Party endpoints for sending game data to all players in the game session network.
Player A, Player B, and Player C continue to chat with each other throughout the game session via the fire
team network.
When the game session ends, all players leave its respective Party network but the fire team Party network
remains active and its participants continue chatting without any disruptions.
The key takeaway from this example is that the extra Party network enabled real-time communication beyond
the lifetime of a single game session for a group of active players.
Multiple networks wouldn't have been appropriate if players were only partitioned into teams within the game
session. In that scenario, it would be better to use chat permissions in a single Party network to define each
team's chat boundaries.
Additionally, using multiple networks would've been inappropriate if the long-lived group didn't represent
players actively communicating with each other—for example, Guilds or chat-less lobbies. For these non-real-
time scenarios, other features such as PlayFab Lobbies or PlayFab Entity Groups may be more appropriate.

Endpoints vs Chat Controls across multiple networks


It's worth noting that Party endpoints and Party chat controls interact with multi-network scenarios in different
ways.
Endpoints represent a data messaging channel created for a specific network. An endpoint from one network
can't send messages to an endpoint on another network.
Chat controls, on the other hand, more closely represent individual players. A single user can only have one chat
control. Each chat control can be connected to multiple networks simultaneously, and chat controls can
communicate across networks as long as the user associated with the given chat control is authenticated to all
associated networks. Whether using a single network or multiple networks, defining communication boundaries
between chat controls should be achieved with chat permissions.

Cost
PlayFab Party's usage measurement is impacted by the number of networks a player is connected to. The Party
Connectivity billing meter is calculated per-network, so using multiple networks simultaneously costs more than
using a single network. Be sure to consider the cost-impact when planning your game architecture.
You can view more information about PlayFab Party costs on the PlayFab Party Pricing page.
PlayFab Party Pricing
5/24/2022 • 2 minutes to read • Edit Online

There are four key meters used to bill Party utilization:


1. Par ty connectivity. This is measured in player minutes connected to a network. Metering starts when a
player creates a network or joins a network, and it stops when they have disconnected.
2. Par ty voice. This is measured in player minutes speaking. When a player is connected to a network and is
actively speaking, that player voice activity is measured and metered.
3. Par ty Cognitive Ser vices This is measured in player minutes using Speech to Text, Text to Speech, or
Translation features.
4. Network egress. This is data sent from PlayFab's relay and voice servers. This is congruent to the aggregate
amount of data that players receive from the network.
You can view the current Party rates on the PlayFab pricing page. You can also use this Party pricing calculator to
get the ballpark estimate of your monthly bill.
PlayFab Party QoS measurements
5/24/2022 • 2 minutes to read • Edit Online

PlayFab Party performs background Quality of Service (QoS) measurements to provide titles low-latency access
to remote Azure resources. Here we'll outline the core scenarios where titles should expect to encounter Party's
QoS features.

Understanding when QoS is measured


The Party library begins measuring QoS as soon as Party is initialized. Once Party successfully measures QoS,
the only way to refresh these measurements is to cleanup and re-initialize the Party library. If measuring QoS
fails, the Party library will retry the measurement the next time you call PartyManager::CreateNewNetwork.

Selecting regions for Party networks


The primary reason PlayFab Party measures QoS is to enable titles to use latency data when selecting the Azure
region in which a Party network is hosted.
Without waiting to inspect QoS measurement results, titles can call PartyManager::CreateNewNetwork with an
empty list of preferred regions to allocate a network in the current lowest-latency region.

uint32_t regionCount = 0;
const PartyRegion* regionList = nullptr;

PartyError error = PartyManager::GetSingleton().CreateNewNetwork(


localUser,
&networkConfiguration,
regionCount,
regionList,
nullptr,
nullptr,
nullptr,
nullptr);

Alternatively, titles can inspect the Party library's QoS measurement results and select a list of preferred regions
based on title-specific criteria.
To inspect QoS measurement results, wait to receive a successful PartyRegionsChangedStateChange from
PartyManager::StartProcessingStateChanges.

switch (stateChange->stateChangeType)
{
case PartyStateChangeType::RegionsChanged:
{
auto regionsChanged = static_cast<PartyRegionsChangedStateChange*>(stateChange);
if (regionsChanged.result == PartyStateChangeResult::Succeeded)
{
m_qosResultsReady = true;
}
}

// ...
}
Then call PartyManager::GetRegions to inspect and evaluate the current list of regions and latencies.

if (m_qosResultsReady)
{
uint32_t regionCount;
const PartyRegion* regionList;

PartyError error = PartyManager::GetSingleton().GetRegions(


&regionCount,
&regionList);
if (PARTY_FAILED(error))
{
DEBUGLOG("PartyManager::GetRegions failed: %s\n", PartyManager::GetErrorMessage(error));
return;
}

// Prevent Party from using Azure regions above some latency threshold.
// The game is unplayable in those scenarios.
std::vector<PartyRegion> filteredRegionList = OmitRegionsAboveMaxLatency(regionCount, regionList,
maxLatency);

error = PartyManager::GetSingleton().CreateNewNetwork(
localUser,
&networkConfiguration,
filteredRegionList.size(),
filteredRegionList.data(),
nullptr,
nullptr,
nullptr,
nullptr);
if (PARTY_FAILED(error))
{
DEBUGLOG("PartyManager::CreateNewNetwork failed: %s\n", PartyManager::GetErrorMessage(error));
return;
}

Regional price differences


Keep in mind that all Party regions are not charged equally. For information about regional price differences, see
our pricing page.

Using optimal regions for accessible chat features


The other reason PlayFab Party measures QoS is to enable more responsive chat accessibility features: text-to-
speech synthesis, speech-to-text transcription, and translation. These accessibility features use regional Azure
Cognitive Services resources, and measuring QoS enables optimal use of the different regions.

Understanding failures to measure QoS


Because network creation and chat accessibility features rely on QoS measurements, it's valuable to inspect the
result and error detail of the PartyRegionsChangedStateChange. Failures in this state change may provide
helpful debugging context for later failures.
Supported Azure regions
5/24/2022 • 2 minutes to read • Edit Online

PlayFab Party networks can be created in the following Azure regions:


Australia East
Australia Southeast
Brazil South
Central US
East Asia
East US
East US 2
Japan East
Japan West
North Central US
North Europe
South Africa North
South Central US
Southeast Asia
West Europe
West US
Network egress charges depend on the regions in which your Party networks are hosted.

ZONE REGIO N S

Zone 1 West US, East US, North Central US, South Central US, East
US 2, Central US, West Europe, North Europe

Zone 2 East Asia, Southeast Asia, Japan East, Japan West, Australia
East, Australia Southeast

Zone 3 Brazil South, South Africa North

For more information about region selection, see Selecting regions for Party networks.
You can view the current Party rates on the PlayFab pricing page.
For more information about Azure regions, see the Azure documentation.
PlayFab Party release notes
5/24/2022 • 9 minutes to read • Edit Online

PlayFab Party had a significant (up to 90%) price drop on 10/13/2020. You can view the updated Party rates on
the Pricing page. For more information about the price drop, see our blog post.

1.7.8
April 21, 2022
Bug fixes
Fixed an issue where memory wasn't fully cleaned up when PartyManager::Cleanup() was called.
Fixed an issue where calling PartyLocalChatControl::SetAudioInput() or
PartyLocalChatControl::SetAudioOutput() with the same audio device selection would unnecessarily result in
the library reinitializing the audio device.

1.7.7
Mar 16, 2022
Bug fixes
Playstation4, Playstation5: Fixed a crash that occurred when there was no audio device after the audio
devices were removed.
Switch: Fixed an issue that caused web requests to fail when multiple PlayFab transactions were triggered.

1.7.6
Feb 8, 2022
Performance improvements
Windows, XDK, Nintendo Switch, Playstation4, Playstation5: Removed two worker threads and perform
relevant work on a preexisting, lower frequency work thread. The Microsoft Game Development Kit (GDK)
version of the library already had this coalesced work behavior.
Bug fixes
iOS, Android, Switch, Playstation4, Playstation5, and Stadia: Fixed a small amount of memory allocated
during initialization not being properly freed during cleanup.
Avoid reporting PartyChatTextReceivedOptions::FilteredDueToError flag in PartyChatTextReceivedStateChange
when text moderation is not enabled.

1.7.5
Sep 30, 2021
Bug fixes
Fixed an issue where some 16kHz microphones were not working.
Fixed an issue where microphone permission changes were not handled on Windows.
Fixed a memory leak in some PartyManager::CreateNewNetwork() failure conditions.
Fixed an occasional crash in PartyLocalEndpoint::GetEndpointStatistics() .
1.7.0
Jun 29, 2021
New profiling hooks and chat control indicators
Developers interested in where time is spent in internal library functions can now install optional method
entrance and exit callbacks to hook into their preferred high-performance instrumentation method. For more
information, see PartyManager::SetProfilingCallbacksForMethodEntryExit . In this release the callbacks are only
supported for Windows, Xbox One XDK, and Microsoft Game Core platforms.
New NoRemoteInput and RemoteAudioInputMuted chat control indicators provide more granularity on
currently silent audio state. For more information, see PartyChatControlChatIndicator .
Endpoint message behavior improvements
The 'PartySendMessageQueuingConfiguration' timeoutInMilliseconds field is now also evaluated by the
transparent cloud relay if forced to queue messages before forwarding because of differing network
conditions or responsiveness of the remote targets.
When fully authenticated into a network, sending to a 0-entry array will correctly target the exact set of all
remote endpoints the library currently reports in the network at that time. Endpoints being created while the
message is in the process of transmitting are no longer potentially included.

1.6.1
Bug fixes
Fixed a bug where a crash may occur when a chat control is connected to a network while that same chat
control is disconnecting from another network.

1.6.0
Apr 12, 2021
New thread control and text moderation features
The library's work can now be run manually on game-controlled threads. For more information, see
PartyManager::SetWorkMode .
Offensive text chat can now optionally be filtered. For more information, see Using text moderation.
Explicit enum numbering in the header
Enum values in the header now have explicit numbering.

1.5.13
Mar 26, 2021
Bug fixes
Fixed a bug where audio is cutting out on iOS devices using Bluetooth headsets.
Fixed a bug where an incorrect error code is generated when the app doesn't have permission to activate a
microphone on Windows platforms.
Fixed a bug where an unhealthy device is never refreshed unless something else forces a refresh.
Fixed a bug where a crash may occur when dereferencing a send channel's user data after the source
endpoint associated with that channel has become invalid.
Fixed a bug where clients experience silent failures if a remote chat control doesn't have a language code.

1.5.10
Bug fixes
Fixed a bug where the library may fail to initialize on some Windows devices due to a mismatch between the
processor affinity of the process and the library's default thread affinity.
Fixed a bug where the library may not provide errors when an operation fails due to an internal web request
failure.
Fixed a bug where a crash may occur when direct peer connectivity is enabled and the library attempts to
establish direct peer connectivity to another device.
Fixed a bug that may result in crackly or distorted audio.

1.5.1
Sep 05, 2020
Bug fix
Fixed a bug where the library may fail to activate the microphone on iOS.

1.5.0
New direct peer-to -peer connectivity, latency, and speech-to -text features
Direct peer-to-peer connectivity is now supported in the Windows 10 and Microsoft Game Core versions of
the library. For more information, see Using direct peer-to-peer connectivity.
The round trip latency between the local device and a remote device can now be queried through the library.
For more information, see PartyEndpointStatistic::AverageDeviceRoundTripLatencyInMilliseconds
Speech-to-text profanity masking can now be disabled. For more information, see
PartyVoiceChatTranscriptionOptions::DisableProfanityMasking .

Android and iOS audio bug fixes


Android: Bluetooth manager will be initialized the first time PartyLocalDevice::CreateChatControl() is called,
rather than when PartyManager::Initialize() is called.
iOS: Fixed a minor sound artifact when PartyManager::Initialize() is called.

1.4.13
Windows 8.1 dependency issue
This release removes an unnecessary dependency on api-ms-win-core-version-l1-1-1.dll which prevented
previous versions from working on Windows 8.1

1.4.8
Apr 30, 2020
TLS1.2
The transcription stack has been updated to use TLS1.2 on Windows 7, Android, and iOS. Please upgrade if
you make use of any of these platforms as TLS1.1 support will be deprecated by Azure Speech Services
beginning in September 2020. All other platforms already support TLS1.2 and no upgrade is necessary.
Bug fixes
Fixed a bug where the languageCode field in the PartyCreateChatControlCompletedStateChange struct was not
being populated.
Fixed a bug which was artificially inflating the latency measurements reported by
PartyManager::GetRegions() .
Fixed a bug which allowed PartyManager::SetMemoryCallbacks() to be called at unsafe times.
Fixed a bug where calling PartyManager::DestroyLocalUser() with a PartyLocalUser in a PartyNetwork would
generate a PartyLocalUserRemovedStateChange with an incorrect value in the removedReason field,
PartyLocalUserRemovedReason::RemoveLocalUser , instead of the correct value,
PartyLocalUserRemovedReason::DestroyLocalUser .

Misc changes
The bandwidth used by chat data has been reduced.
More descriptive error codes and error messages are now provided when sandbox issues are encountered
on Xbox.
PartyManager::Initialize() will now fail if an empty PlayFab Title ID is provided.
Passing invalid PlayFab Entity Tokens to PartyManager::CreateLocalUser() will now result in more descriptive
error messages in the state change results for operations which rely on a valid token.
Typos in the header documentation have been fixed.
A more descriptive error code and error message is now provided when an invalid region is passed to
PartyManager::CreateNewNetwork() .
The documentation for the lifetimes of PartyString values has been clarified for the structures and
interfaces in Party.h.
The documentation for PartyManager::Cleanup() was clarified to explain it is not a thread-safe call.
A more descriptive error code and error message are provided when PartyManager::ConnectToNetwork()
asynchronously fails with internet connectivity errors.

1.3.0
Chat API Changes
The real-time audio manipulation functions, which can be used to modify outgoing or incoming voice chat
audio, are implemented for Windows and Xbox. For more information, see Using real-time audio
manipulation to apply custom voice effects.
The chat permission options have more options for optionally configuring text-to-speech and microphone
audio permissions independently. For more information, see PartyChatPermissionOptions .
This breaks compatibility with previous releases of the Xbox Live Helper library. This release is compatible
with version 1.2.0 of the Xbox Live Helper library. For more information, see the Xbox Live Helper Library
release notes.
Each transcription state change now indicates whether it represents text-to-speech or microphone audio. For
more information, see PartyVoiceChatTranscriptionReceivedStateChange .

1.2.2
iOS Changes
Adds support for the volume control API.

1.2.0
Android Changes
Adds support for the volume control API.
Removes audio focus handling from the library. Host applications are now expected to implement their own
focus handling logic.

1.0.2
Fixed crash in background telemetry
1.0.1
Party API Changes
PartyManager::SetMemoryCallbacks Changes
This release of Party adds fixes for PartyManager::SetMemoryCallbacks() and also restrictions about when this API
is safe to call. Check the reference documentation of the API in Party.h for details.
Removal of PartyStateChangeResult::TitleCreateNetworkThrottled
The PartyStateChangeResult value TitleCreateNetworkThrottled has been removed from the API, since the Party
library will never generate it.

0.7.0-prerelease
Windows Packaging Changes
This release of Party introduces a new NuGet package, Microsoft.PlayFab.PlayFabParty.Cpp.Windows, which
replaces and deprecates the NuGet packages specific to Windows 10 and Windows 7
(Microsoft.PlayFab.PlayFabParty.Cpp.Win10 and Microsoft.PlayFab.PlayFabParty.Cpp.Win7, respectively). The new
unified Windows NuGet package contains two new DLLs, PartyWin.dll (supports Windows 8.1 and up) and
PartyWin7.dll (only for use on Windows 7). With the new Windows unified NuGet package, the correct Party DLL
is loaded based on runtime detection of the OS version, so both PartyWin.dll and PartyWin7.dll should be
included in the game distribution package.
Android Changes
The Android flavor now uses a shared object for Party (libparty.so) instead of a static library (libparty.a).
This release also contains Android-specific bug fixes for audio device selection.
iOS Changes
The iOS flavor of Party now has the framework package included for dynamically loading libparty instead of the
statically built libparty.a.
API Changes
UpdateEntityToken API
This release of Party makes a change related to the handling of PlayFab entity tokens. In the previous version,
the game provided Party with a user's entity token in the PartyManager::CreateLocalUser() API. Thereafter, Party
internally refreshed the entity token and kept it up to date.
In this version, the internal token refreshing behavior has been removed and is replaced by a new API,
PartyLocalUser::UpdateEntityToken() . The caller is now responsible for monitoring the expiration of the entity
token provided to PartyManager::CreateLocalUser() and PartyLocalUser::UpdateEntityToken() . When the token
is nearing or past the expiration time a new token should be obtained by performing a PlayFab login operation
and provided to the Party library by calling PartyLocalUser::UpdateEntityToken() . It is recommended to acquire
a new token when the previously supplied token is halfway through its validity period. On platforms that may
enter a low power state or otherwise cause the application to pause execution for a long time, preventing the
token from being refreshed before it expires, the token should be checked for expiration once execution
resumes.
The rough flow is as follows:
1. The game calls a LoginWith* PlayFab API
2. The response from PlayFab contains the entity token and also the expiration time
3. Provide the token information to Party with the PartyManager::CreateLocalUser() API, as before
4. [New] Make note of the expiration time in order to know when to refresh it
5. [New] At halfway through the token's expiration time (or soonest opportunity after that time), acquire a fresh
token by calling LoginWith* again and track the new token's expiration time
6. [New] Call PartyLocalUser::UpdateEntityToken() to pass in the new token to Party

Additional notes:
The act of acquiring an entity token does not invalidate any previously obtained entity tokens. They remain
valid until they expire.
The internal refreshing functionality was removed because most games are expected to make their own
PlayFab calls and so having both the game and the Party library fetching entity tokens causes unnecessary
service load to basically manage two sets of tokens.
Chat API Changes
The PartyVoiceChatTranscriptionReceivedStateChange now includes a languageCode field, which indicates the
language of the transcription.
The PartyChatTextReceivedStateChange now includes a languageCode field, which may indicate the language of
the chat text. The languageCode field will be populated when chat text translation has been enabled via
PartyLocalChatControl::SetTextChatOptions() .

0.6.0-prerelease
Added support for iOS, Android, and Nintendo Switch platforms.
For more information, see the following links:
iOS/Android
Nintendo Switch

0.5.0-prerelease
API Changes
Accessible Chat
Added support for text-to-speech narration. (see PartyLocalChatControl::SetTextToSpeechProfile() )
Added more options for controlling when speech-to-text occurs. (see
PartyLocalChatControl::SetTranscriptionOptions() )
Added text-to-text translation to the API, although it is not yet supported. ( see
PartyLocalChatControl::SetTextChatOptions() )
Reduced text-to-speech bandwidth and memory usage.
Network access control
PartyNetwork::SetAccessControlList() and related methods have been removed from the API. Use the new
PartyInvitation class and related methods to create open invitations or grant access to specific PlayFab
users to your Party networks.

0.4.6-prerelease
API Changes
Added new public API PartyLocalUser::UpdateEntityToken() .

0.2.0-prerelease
API Changes
PartyManager::Initialize now requires a valid PlayFab Title ID to be passed in.
What is PlayFab Insights?
5/24/2022 • 2 minutes to read • Edit Online

NOTE
The PlayFab Insights feature is in public preview. We anticipate ongoing changes to it as we continue gathering feedback
and optimizing for customer use.

PlayFab Insights is a completely managed data environment, giving you instant access to your games data
without the need for additional engineering. Unlike other hosted data solutions Insights requires no setup, no
GDPR work, and no extra engineering. Simply use PlayFab services and your data is available. Automatically
ingest and scale, connect external visualization tools, and query freely.

Key Features
Insights key features revolve around data cluster management, data retention, ingestion options and
connectivity to outside tools.
Automatic Ingestion
PlayFab services automatically fire Playstream events. Any events fired by PlayFab services or created through
our SDK are automatically routed to your Insights cluster. There is no need to worry about defining schema or
DDL from automatic events. However, the option for sending your own custom events is available. For more
information about sending custom events, see the Custom event overview of Generating PlayStream events.
Change Your Performance Level To Meet Your Needs

Match your cluster performance to your needs minute by minute. Slide your performance level up or down or
alternatively schedule your cluster to have different performance levels automatically using scheduled tasks. See
Performance Level & Retention for details.
Schedule Your Performance Level
Use standard cron expressions to automically scale your cluster up and down during known times. See
Scheduled Scaling for details.
Keep Your Data as Long as You Need

Never delete your data or clear your data out every 30 days, whatever is needed for your studio. See
Performance Level & Retention for details.
Connect Outside Tools
Connect PowerBI or Grafana for visualization, automate data jobs with Python or Azure Data Factory, explore
your data with Azure Data Explorer. See Connectivity for details.
Export Original or Cleaned Data
Use the automated export service to export all your data to Azure Blob or AWS S3. See Exporting Data for
details.
Bring Your Own Datasets
Ingest your own custom datasets with Management Commands. Merge your custom Playstream events,
standard Playstream events, and custom uploaded data to create more robust datasets.
GDPR Compliant
Standard reporting is tracked and GDPR compliant. Simply call the playfab GDPR delete request and well do the
rest. Have custom data you need to delete? No problem, use the Management Commands to maintain your
custom data.

Getting Started with PlayFab Insights


PlayFab Insights is available to all studios right out of the box. The only thing needed to get started is some data.
Implement any PlayFab service and you will get playstream events automatically sent to your Insights or you
can send telemetry directly using PlayFab API calls. Once you have some data check out Data Explorer and the
Insights Overview.

What Services are Powered by Insights?


PlayFab Insights powers a variety of features and functionality across Game Manager. Adjusting the
performance level will affect the following across your title:
Data
Data Explorer (Preview)
Event Export
Management (Preview)
Dashboards
Trends (Preview)
Reports
Players
Player Logins
Player Event History
Multiplayer
Party Usage Charts
Connecting external tools to Insights
5/24/2022 • 2 minutes to read • Edit Online

PlayFab Insights offers an unprecedented look into your game's data and the trends created by your users. Part
of Insights' power is the flexibility to be paired with many other data and analytics tools. This section contains
tutorials that show you how to connect Insights to other tools.
Currently, you can connect the following external tools to Insights:
Connect to Power BI
Connect to Kusto Explorer
Connect to Azure Data Explorer (ADX)
Connect to Azure Data Factory (ADF)
Connect to Grafana
Connect to Python
Connect to Kusto C# SDK

Power BI
Pairing Power BI with Insights allows you to easily create visualizations of your game data.
To get started, go to the tutorial Connecting Power BI to Insights.

Kusto Explorer
Kusto Explorer is a rich desktop application that allows you to explore your game data using Kusto query
language.
To get started, go to the tutorial Connecting Kusto Explorer to Insights.

Azure Data Explorer (ADX)


Azure Data Explorer is a scalable data exploration service that allows you to discover relevant insights into your
game data using a SQL-like query language.
To get started, go to the tutorial Connecting Azure Data Explorer to Insights.

Azure Data Factory (ADF)


Azure Data Factory is a managed cloud service and data integration service that allows you to create workflows
for orchestrating data movement and transforming data at scale. You can supplement your game data with the
proper context to extract meaningful insights.
To get started, go to the tutorial Connecting Azure Data Factory to Insights.

Grafana
Grafana is an open-source tool for running analytics and monitoring systems. It pulls data from Insights to
maintain dashboards with a wide variety of visualization options.
To get started, go to the tutorial Connecting Grafana to Insights.
Python
You have the option to connect Python to Insights and query your game data with it, including using the library
from Jupyter Notebooks.
To get started, go to the tutorial Connecting Python to Insights.

Kusto C# SDK
The Kusto C# SDK offers all the capabilities of Kusto, with the additional ability to query Insights from Azure
functions.
To get started, go to the tutorial Connecting Kusto C# SDK to Insights.
Tutorial: Create an Azure Active Directory (AAD)
Application to use with Insights
5/24/2022 • 2 minutes to read • Edit Online

This tutorial covers creating an Azure Active Directory (AAD) application to use with Insights, which is one of the
prerequisites for connecting the following tools with Insights:
Azure Data Factory (ADF)
Grafana
Python

Prerequisites
An Azure account with an active subscription. Create an account for free

Create an Azure Active Directory (AAD) application


To create an AAD application to link to your title database:
1. Log into the Azure portal. If you don't have an Azure subscription, create a free account.
2. After logging into the portal, use the search bar to find and select App Registrations . Then, select New
registration in the upper left-hand corner.

3. In the Register an application window enter a name for your registration, then select which account
types you would like this registration to support. (If you need help deciding, select the Help me choose
link which will open a window with more information.)
4. Select Register . You will be directed to a page with an overview of your newly-registered applcation.
Save the Application (client) ID and Director y (tenant) ID somewhere (you will need these later).
5. In the navigation panel on the left-hand side select Cer tificates & secrets -> New client secret .

6. Enter a description for the secret and select how long you would like it to be valid.
7. Select Add , and the new secret will appear below Client secrets . Now make sure to copy the secret key
and save it somewhere secure. It's essential that you do this now, since you won't be able to access the
secret key once you leave this page.

Connect the AAD app to your title database


Now we will connect the Azure app to your title database.
1. From the Explorer page in GameManager or in Kusto.Explorer, run the following command, replacing
with your own Title ID and client/tenant ID:

.add database <titleID> Admin ('aadapp=<app/client ID>;<tenant ID>')

titleID is case sensitive, so make sure it is in all caps.

You can verify that this command was successful by going to the Users page in GameManager. There
should be an entry that matches the Client/Tenant ID.
Note that this will make the Azure app an Admin on your game in PlayFab. If you would like the Azure
app to have lesser permissions, assign the Azure app a custom role in PlayFab that only has permissions
for the Kusto database. The necessary permissions are:
Explorer data & tab .
Analytics data read access , to run queries and simple management commands.
Analytics data write access , to create/drop tables, alter retention policy, ingest data, purge.

Next steps
Now that you have created an Azure app and linked it to your title database, follow the steps to connect
your tool of choice with Insights:
Connect with Azure Data Factory (ADF)
Connect with Grafana
Connect with Python
Tutorial: Connecting Power BI to Insights
5/24/2022 • 2 minutes to read • Edit Online

This guide helps you get started using Power BI along with Insights. After connecting, you can use Power BI to
create visualizations of your game data and more. To learn more about other tools you can connect Insights
with, see Connecting external tools to Insights.

Prerequisites
PlayFab account authenticated with AAD
You need a PlayFab account or user for which the authentication provider is set to Microsoft. The
Microsoft authentication provider uses Azure Active Directory (AAD) for authentication which is required
to use the Azure services. See Azure Active Directory Authentication for Game Manager for instructions
on creating an AAD-authenticated account or user.
To verify that the account, or user, is set to use the Microsoft authentication provider:
Visit the PlayFab log in page.
Use the the Sign in with Microsoft link to access your PlayFab account.
If you can sign in, then the account is set to use the Microsoft authentication provider.
Game Manager permissions for Insights
You need to assign your account a user role with the following Game Manager permissions enabled:
Admin status.
Access to the Explorer tab and associated data.
Read and write access to Analytics data.
You can either create a new user role or add these permissions to an existing role.
Other prerequisites
Power BI for desktop
Note that running Power BI for Desktop is required, this scenario is not supported in the PowerBI Web
Portal.

Connect with Power BI


On your local machine, open Power BI.
1. In the Power BI Desktop window, select Get Data > Azure Data Explorer (Kusto) .
2. In the Azure Data Explorer (Kusto) dialog box take the following steps:
Under Cluster enter the PlayFab API endpoint, which is https://insights.playfab.com .
Under Database enter your title ID in all uppercase, as Database names are case sensitive.
Scroll down, and under Data Connectivity mode select DirectQuer y .
Optionally, enter a table or query. You can set limits for max records or max size. If your query exceeds
these limits, it returns a PartialQueryFailure error and a message stating that you exceeded the limits.
The following example specifies a query on the table events.all that returns events occurring in the last
seven days.
3. Select OK . You can now execute queries and commands on the database.

Additional resources
Power BI documentation
To learn about other tools to connect to Insights, see Connecting external tools to Insights
Tutorial: Connecting Kusto Explorer to Insights
5/24/2022 • 2 minutes to read • Edit Online

This guide helps you get started using Kusto Explorer along with Insights. After connecting, you can use Kusto
Explorer to query and explore your game data. To learn more about other tools you can connect Insights with,
see Connecting external tools to Insights.

Prerequisites
PlayFab account authenticated with AAD
You need a PlayFab account or user for which the authentication provider is set to Microsoft. The
Microsoft authentication provider uses Azure Active Directory (AAD) for authentication which is required
to use the Azure services. See Azure Active Directory Authentication for Game Manager for instructions
on creating an AAD-authenticated account or user.
To verify that the account, or user, is set to use the Microsoft authentication provider:
Visit the PlayFab log in page.
Use the the Sign in with Microsoft link to access your PlayFab account.
If you can sign in, then the account is set to use the Microsoft authentication provider.
Game Manager permissions for Insights
You need to assign your account a user role with the following Game Manager permissions enabled:
Admin status.
Access to the Explorer tab and associated data.
Read and write access to Analytics data.
You can either create a new user role or add these permissions to an existing role.
Other prerequisites
Kusto.Explorer

Connect with Kusto Explorer


On your local machine, open Kusto.Explorer.
1. Add a connection. You can do this in two different ways:
Select the Connections tab, then select Add connection .
Right-click on the Connections folder in the left navigation panel, then select Add connection .
2. In the Add connection dialog box:
Under Cluster connection enter the PlayFab API endpoint, which is https://insights.playfab.com .
Under Security , make sure AAD Federated is selected.
Expand the Advanced: Connection String box and change the value of Initial Catalog from
NetDefaultDB to <titleID> . Note that <titleID> must be all uppercase here. In the example below,
this change is highlighted in the string.
3. Select OK , and you should now be able to visualize the results of the query.

Additional resources
Kusto Explorer documentation
To learn about other tools to connect to Insights, see Connecting external tools to Insights
Tutorial: Connecting Azure Data Explorer to Insights
5/24/2022 • 2 minutes to read • Edit Online

This guide helps you get started using Azure Data Explorer (ADX) along with Insights. After connecting, you can
use Azure Data Explorer to query your game data and discover relevant insights. To learn more about other
tools you can connect Insights with, see Connecting external tools to Insights.

Prerequisites
PlayFab account authenticated with AAD
You need a PlayFab account or user for which the authentication provider is set to Microsoft. The
Microsoft authentication provider uses Azure Active Directory (AAD) for authentication which is required
to use the Azure services. See Azure Active Directory Authentication for Game Manager for instructions
on creating an AAD-authenticated account or user.
To verify that the account, or user, is set to use the Microsoft authentication provider:
Visit the PlayFab log in page.
Use the the Sign in with Microsoft link to access your PlayFab account.
If you can sign in, then the account is set to use the Microsoft authentication provider.
Game Manager permissions for Insights
You need to assign your account a user role with the following Game Manager permissions enabled:
Admin status.
Access to the Explorer tab and associated data.
Read and write access to Analytics data.
You can either create a new user role or add these permissions to an existing role.

Connect with Azure Data Explorer (ADX)


To connect with Azure Data Explorer:
1. Open Azure Data Explorer. Select Add Cluster .
2. Enter the PlayFab API endpoint, which is https://insights.playfab.com .
3. Select Add . Now are you able to execute queries or commands on the database.

Additional resources
Azure Data Explorer documentation
To learn about other tools to connect to Insights, see Connecting external tools to Insights
Tutorial: Connecting Azure Data Factory (ADF) to
Insights
5/24/2022 • 3 minutes to read • Edit Online

This guide helps you get started using Azure Data Factory (ADF) along with Insights. After connecting, you can
use Azure Data Factory to create workflows for orchestrating data movement and transforming game data at
scale. To learn more about other tools you can connect Insights with, see Connecting external tools to Insights.
In this tutorial you learn how to:
Create a data factory in Azure
Create a pipeline

Prerequisites
PlayFab account authenticated with AAD
You need a PlayFab account or user for which the authentication provider is set to Microsoft. The
Microsoft authentication provider uses Azure Active Directory (AAD) for authentication which is required
to use the Azure services. See Azure Active Directory Authentication for Game Manager for instructions
on creating an AAD-authenticated account or user.
To verify that the account, or user, is set to use the Microsoft authentication provider:
Visit the PlayFab log in page.
Use the the Sign in with Microsoft link to access your PlayFab account.
If you can sign in, then the account is set to use the Microsoft authentication provider.
Game Manager permissions for Insights
You need to assign your account a user role with the following Game Manager permissions enabled:
Admin status.
Access to the Explorer tab and associated data.
Read and write access to Analytics data.
You can either create a new user role or add these permissions to an existing role.
Other prerequisites
Create an Azure Active Directory (AAD) application and connect it to your title database

Create a new data factory


To create a new data factory:
1. Sign in to the Azure portal. From the homepage under Azure Ser vices , select Create a resource .
Search for Data Factor y , select it and then select Create .
2. Fill out the required fields:
For Name , choose a name for your data factory. The name must be globally unique.
For Subscription , select your Azure subscription in which you want to create the data factory.
For Resource Group , use one of the following steps:
Select Use existing , and select an existing resource group from the list.
Select Create new , and enter the name of a resource group.
You do not need to enable GIT right now, so uncheck the box below.

3. Select Create . After the deployment completes, under Next steps select Go to resource .
4. To open the Data Factory UI in a separate tab, select Author & Monitor .

Create a pipeline
We are now going to create a new pipeline to get data from Insights. To create a pipeline:
1. On the Let's get star ted page, select Create pipeline .
2. In the Activities panel under Azure Data Explorer , drag and drop an Azure Data Explorer
Command into the blank workspace. In the bottom panel under General , fill out the name and
description.

3. Select the Connection tab and select New .

4. In the New linked ser vice (Azure Data Explorer (Kusto)) window, fill out the fields:
For Name , use the Title ID.
For Account selection method , select Enter manually .
For the Endpoint , use the PlayFab API endpoint, which is https://insights.playfab.com .
For Ser vice Principal ID , enter your Client ID from your Azure app.
For Ser vice Principal Key , enter your Client secret from your Azure app.
In the Database box, type the Title ID in all upper case.
Select Create . Now the pipeline is ready. You can go back to the main pipeline view by clicking the
pipeline name.
5. To verify that all of the information is correct, select Test connection . If everything is set up correctly, it
returns a Connection successful response.
3. To validate and debug the pipeline, in the toolbar above the workspace, select Validate and then select
Debug .

Additional resources
Azure Data Factory (ADF) documentation
To learn about other tools to connect to Insights, see Connecting external tools to Insights
Tutorial: Connecting Grafana to Insights
5/24/2022 • 3 minutes to read • Edit Online

This guide helps you get started using Grafana along with Insights. After connecting, you can use Grafana to run
analytics and monitoring systems on your game data from Insights. To learn more about other tools you can
connect Insights with, see Connecting external tools to Insights.
In this tutorial you learn how to:
Set up Grafana for Insights
Create a data source in Grafana
Create a dashboard in Grafana
Run Kusto queries and commands using the dashboard

Prerequisites
PlayFab account authenticated with AAD
You need a PlayFab account or user for which the authentication provider is set to Microsoft. The
Microsoft authentication provider uses Azure Active Directory (AAD) for authentication which is required
to use the Azure services. See Azure Active Directory Authentication for Game Manager for instructions
on creating an AAD-authenticated account or user.
To verify that the account, or user, is set to use the Microsoft authentication provider:
Visit the PlayFab log in page.
Use the the Sign in with Microsoft link to access your PlayFab account.
If you can sign in, then the account is set to use the Microsoft authentication provider.
Game Manager permissions for Insights
You need to assign your account a user role with the following Game Manager permissions enabled:
Admin status.
Access to the Explorer tab and associated data.
Read and write access to Analytics data.
You can either create a new user role or add these permissions to an existing role.
Other prerequisites
Create an Azure Active Directory (AAD) application and connect it to your title database

Get set up with Grafana


1. There are two ways to get Grafana. You can create a free account and download Grafana to run on your
computer. Or, if you have a paid Grafana Cloud subscription, you can use your online hosted instance.
2. Install the Azure Data Explorer plugin for Grafana.

Create a new data source in Grafana


Now that your title database is linked to an Azure app, you can use the app to connect with Grafana. To create a
new data source:
1. Log in to Grafana.
2. On the Welcome to Grafana page, select Add data source .
3. On the Add Datasource page, select the Azure Data Explorer Datasource . You can search for it with
the searchbar or find it listed under the section Others . If you don't see the Azure Data Explorer
Datasource option, you need to install the Azure Data Explorer Datasource For Grafana plugin.

4. On the Azure Data Explorer Datasource configuration page:


For Cluster URL , enter the PlayFab API endpoint, which is https://insights.playfab.com .
Enter your Tenant Id , Client Id , and Client secret from your Azure Active Directory (AAD)
application into their respective fields.
Select Save & Test . You should see a Connection Successful return message.
From Default Database , select your Title ID or database name. This automatically populates after
you successfully save and test the datasource. If it doesn't show up after a successful connection, try
exiting and re-opening the configuration page.

Create a dashboard
From the Grafana homepage we will create a new dashboard. To create a dashboard:
1. Select New dashboard .
2. In the New Panel dialog box, select Add Quer y .

3. In the Quer y panel next to Database select your database from the drop-down menu. In this example
the database name is Unicorn Battle .

Run Kusto queries and commands


Now you are going to use your newly-created Dashboard to run Kusto queries and commands on your
database. To run a query:
1. In the Quer y panel next to Format As , select Table from the drop-down menu.
2. Use the icons on the left to switch to the Visualization panel. Select the drop-down menu to the right of
Visualization , then select the Table option.

3. Return to the Quer y tab. Enter a query and select Run . The results appear in the table above the Quer y
tab. In this example, we ran the query ['events.all'] | limit 100 .

Running a Kusto command follows the same process. Enter your command in the Quer y tab and select
Run . The results are displayed above. In this example, we ran the command .show tables .
Additional resources
Grafana documentation
To learn about other tools to connect to Insights, see Connecting external tools to Insights
Tutorial: Connecting Python to Insights
5/24/2022 • 2 minutes to read • Edit Online

This guide helps you get started using Python with Insights. It uses the Azure Kusto Python SDK. After
connecting, you can query your game data with Python and use the library from Jupyter Notebooks. To learn
more about other tools you can connect with Insights, see Connecting external tools to Insights.

Prerequisites
PlayFab account authenticated with AAD
You need a PlayFab account or user for which the authentication provider is set to Microsoft. The
Microsoft authentication provider uses Azure Active Directory (AAD) for authentication which is required
to use the Azure services. See Azure Active Directory Authentication for Game Manager for instructions
on creating an AAD-authenticated account or user.
To verify that the account, or user, is set to use the Microsoft authentication provider:
Visit the PlayFab log in page.
Use the the Sign in with Microsoft link to access your PlayFab account.
If you can sign in, then the account is set to use the Microsoft authentication provider.
Game Manager permissions for Insights
You need to assign your account a user role with the following Game Manager permissions enabled:
Admin status.
Access to the Explorer tab and associated data.
Read and write access to Analytics data.
You can either create a new user role or add these permissions to an existing role.
Other prerequisites
Create an Azure Active Directory (AAD) application and connect it to your title database

Install Python packages


1. Install the following python packages using pip:
azure-kusto-data
azure-kusto-ingest
adal
2. Below is an example script to get started with.
from azure.kusto.data.exceptions import KustoServiceError
from azure.kusto.data.request import KustoClient, KustoConnectionStringBuilder, ClientRequestProperties

from adal import AuthenticationContext

cluster = "https://insights.playfab.com"

# These parameters are taken from your Azure app


client_id = "<Azure app client id>"
client_secret = "<Azure app client secret>"
tenant = "<Azure app tenant id>"

authority_url = "https://login.microsoftonline.com/" + tenant


context = AuthenticationContext(authority_url)

# Acquire a token from AAD to pass to PlayFab


resource = "https://help.kusto.windows.net"
token_response = context.acquire_token_with_client_credentials(resource, client_id, client_secret)

token = None
if token_response:
if token_response['accessToken']:
token = token_response['accessToken']

kcsb = KustoConnectionStringBuilder.with_aad_application_token_authentication(cluster, token)


client = KustoClient(kcsb)

db = "<title id>"
query = "['events.all'] | count"

# Force Kusto to use the v1 query endpoint


client._query_endpoint = cluster + "/v1/rest/query"

crp = ClientRequestProperties()
crp.application = "KustoPythonSDK"
response = client.execute(db, query)

# Response processing
print(response)

Additional resources
Azure Kusto Python SDK documentation
To learn about other tools to connect to Insights, see Connecting external tools to Insights
Tutorial: Connecting Kusto C# SDK to Insights
5/24/2022 • 2 minutes to read • Edit Online

This guide helps you get started using the Kusto C# SDK along with Insights. After connecting, you can query
your Insights from Azure functions. To learn more about other tools you can connect Insights with, see
Connecting external tools to Insights.

Prerequisites
PlayFab account authenticated with AAD
You need a PlayFab account or user for which the authentication provider is set to Microsoft. The
Microsoft authentication provider uses Azure Active Directory (AAD) for authentication which is required
to use the Azure services. See Azure Active Directory Authentication for Game Manager for instructions
on creating an AAD-authenticated account or user.
To verify that the account, or user, is set to use the Microsoft authentication provider:
Visit the PlayFab log in page.
Use the the Sign in with Microsoft link to access your PlayFab account.
If you can sign in, then the account is set to use the Microsoft authentication provider.
Game Manager permissions for Insights
You need to assign your account a user role with the following Game Manager permissions enabled:
Admin status.
Access to the Explorer tab and associated data.
Read and write access to Analytics data.
You can either create a new user role or add these permissions to an existing role.
Other prerequisites
Create an Azure Active Directory (AAD) application and connect it to your title database

Install packages
1. Install the following NuGet packages:
Required: Microsoft.Azure.Kusto.Data
Optional: Microsoft.Azure.Kusto.Ingest
For more optional packages, see the Kusto .NET SDK documentation
2. Below is some sample code to get started with.

namespace HelloPlayFabInsights
{
using System;
using Kusto.Data;
using Kusto.Data.Common;
using Kusto.Data.Net.Client;

class Program
{
const string Cluster = "https://insights.playfab.com";
const string Database = "<title id>";
const string AzureAuthority = "microsoft.onmicrosoft.com";
const string AzureAuthority = "microsoft.onmicrosoft.com";
const string ClientId = "<app id>";
const string ClientSecret = "<app secret>";

static void Main()


{
var kcsb = new KustoConnectionStringBuilder(Cluster,
Database).WithAadApplicationKeyAuthentication(ClientId, ClientSecret, AzureAuthority);

Console.WriteLine("Run Query...");
RunQuery(kcsb);

Console.WriteLine("Run Command...");
RunCommand(kcsb);

/// <summary>
/// Run a query on your Insights database, and write the results to the console.
/// </summary>
/// <param name="kcsb"></param>
static void RunQuery(KustoConnectionStringBuilder kcsb)
{
using (var queryProvider = KustoClientFactory.CreateCslQueryProvider(kcsb))
{
var query = "['events.all'] | limit 10";

var clientRequestProperties = new ClientRequestProperties() {


Application = "DotNetSDK",
ClientRequestId = Guid.NewGuid().ToString()
};
using (var reader = queryProvider.ExecuteQuery(query, clientRequestProperties))
{
while (reader.Read())
{
string name = reader.GetString(2);
string titleId = reader.GetString(5);
DateTime timestamp = reader.GetDateTime(8);
Console.WriteLine("{0}\t{1}\t{2}", name, titleId, timestamp);
}
}
}
}

/// <summary>
/// Run the ".show tables" command on your Insights database, and write the results to the console.
/// </summary>
/// <param name="kcsb"></param>
static void RunCommand(KustoConnectionStringBuilder kcsb)
{
using (var commandProvider = KustoClientFactory.CreateCslAdminProvider(kcsb))
{
var command = ".show tables";

var clientRequestProperties = new ClientRequestProperties()


{
Application = "DotNetSDK",
ClientRequestId = Guid.NewGuid().ToString()
};
using (var reader = commandProvider.ExecuteControlCommand(command, clientRequestProperties))
{
while (reader.Read())
{
string tableName = reader.GetString(0);
string databaseName = reader.GetString(1);
Console.WriteLine("{0}\t{1}", tableName, databaseName);
}
}
}
}
}
}
}

Additional resources
Azure Kusto .NET Samples
Kusto client library documentation
Data Explorer
5/24/2022 • 2 minutes to read • Edit Online

Overview
Data Explorer is the primary window into event data collected by your title and services. The data is stored in
PlayFab Insights, an in-development offering designed to provide a complete back-end solution for data and
analytics. For more information on the PlayFab Insights vision and strategy, see our webinar.
This feature provides fast indexing and querying on large, diverse data sets. For optimized queries, the engine
can query millions of records in a few seconds - a critical capability for games producing high throughput or
large volumes of gaming events.
Data Explorer has two different querying modes - basic and advanced. Basic mode is designed to let you quickly
discover insights in your event data without requiring query language knowledge. Advanced mode is designed
for more complex queries and deeper insights using the Kusto query language – a SQL-like language optimized
for ad hoc data exploration.
Explorer Advanced uses a simplified SQL-like language that's easy to pick up and learn. The intellisense
capabilities make it possible for users of all skill levels to author complex queries and render the results in-line.
Learn how to get started in the Quickstart section.
Data Explorer Quickstart
5/24/2022 • 2 minutes to read • Edit Online

[NOTE] The Explorer Feature is in public preview. We anticipate ongoing changes to it as we continue
gathering feedback and optimizing for customer use.

Basic mode
To query the data in basic mode:
1. Log in to the PlayFab Game Manager.
2. Select your Title.
3. In the left navigation column, select Data .
4. Select the Data Explorer (basic) tab at the top of the page.
To learn how to author custom Basic queries, see the Getting Started with Data Explorer basic mode tutorial.

Advanced mode
To query the data in advanced mode
1. Log in to the PlayFab Game Manager.
2. Select your Title.
3. In the left navigation column, select Data .
4. Select the Data Explorer (advanced) tab at the top of the page.
5. In the Data Explorer pane, select What’s This to display a set of sample queries.
6. Select Open Sample Quer y under Learning to Query to load the query into the Query pane.
7. Follow the directions in the query comments.
To learn how to author custom queries, see the Getting Started with Data Explorer advanced mode tutorial.
To learn about how to assign roles for read and write data access, see PlayFab User Roles.
Data Explorer Tutorials
5/24/2022 • 2 minutes to read • Edit Online

These tutorials teach you how to use Data Explorer.


Getting started with Data Explorer basic mode
Getting started with Data Explorer advanced mode
Getting started with Data Explorer basic mode
5/24/2022 • 3 minutes to read • Edit Online

IMPORTANT
The Data Explorer feature is in public preview. We anticipate ongoing changes to it as we continue gathering feedback and
optimizing for customer use.

Data Explorer basic mode is designed to let you quickly discover insights in your event data without requiring
query language knowledge. This non-technical query building experience enables users to explore their data
quickly. To learn how to write more complex queries, see the Getting Started with Data Explorer (advanced)
tutorial.

Authoring custom queries


To begin authoring your own queries in basic mode, it's important to first understand the shape of the data
you're accessing.
The events.all table
The events.all table is the default destination for all incoming events. It is a single semi-structured table with
columns for common values such as time & event name. You will quickly become familiar with the EventData
column, which contains the full original JSON payload and is useful in almost all queries. You can read the
following documentation on the events.all table.
Query
A query is composed of one or more Conditions that are combined via the 'OR' logical operator. A condition is
composed of an Event from the event.all table.
Complex conditions can be created by adding one or more Clauses , which is a logical statement composed of a
Variable , Operator , and Value , to a condition. Clauses are combined via the 'AND' logical operator. The
Variables listed in the dropdown are populated based upon the Event selected when creating the Condition.
The timeframe of the query can be adjusted by modifying Star t date and End date .
The output of the query can be modified further by adding Group By and Aggregate Type . Group By modifies
how the output rows are grouped, whereas Aggregate Type modifies how the rows are counted, summed, or
distinct by.
You can create queries in the Query panel. Please note that Data Explorer (basic) queries will only reference the
top 100 events. To view all events, run the query in Data Explorer (advanced).

Query Output
After running a query, you can see the output below in the Query Output panel. The output is in the format of a
bar graph as well as a table.
The graph shows the results for the largest 5 groups. You can see the other groups by clicking the dropdown at
the bottom of the graph.
The table shows the Event Name, Timestamp (UTC), Player ID, and Event Data (via JSON) for reach row.
Sample Queries
Single Condition Queries
What regions are players logging in from this week?

What devices are players logging in from this week?

What's the sum of order totals this week?


Are Playfab limits being exceeded?

Multi Condition Queries


What players and entities are logging in this week?
What items are being purchased or added to inventory this week?

Complex Condition Queries with Clauses


How many "sword" items were purchased this week?
How many items worth between $1 and $5 were purchased this week?

Example queries can be loaded into the Data Explorer basic by selecting “What’s This” and selecting a sample
query.

Limits
There are two limits which govern Data Explorer query usage:
1. Max query runtime: An individual query is not permitted to run longer than 30 seconds. If this limit is
exceeded, the query will be terminated and you will receive an error message.
2. Interval Usage: Each title is permitted a cumulative total runtime of three minutes per any given 10
minute interval. If this limit is exceeded, you will receive an error message and will need to wait before
running additional queries.

Data Retention
By default, Explorer queries run on hot storage, which can be configured in the Management tool. Queries that
search beyond the data stored in hot storage will have significantly longer run times and may time out.
Getting started with Data Explorer advanced mode
5/24/2022 • 5 minutes to read • Edit Online

IMPORTANT
The Data Explorer feature is in public preview. We anticipate ongoing changes to it as we continue gathering feedback and
optimizing for customer use.

Data Explorer advanced mode is designed for more complex queries and deeper insights using the Azure Data
Explorer query language – a SQL-like language optimized for ad hoc data exploration. To learn how to write
non-technical queries, see the Getting Started with Data Explorer basic mode tutorial.

Authoring custom queries


To begin authoring your own queries in advanced mode, it's important to first understand the shape of the data
you're accessing.
The events.all table
The events.all table is the default destination for all incoming events. It is a single semi-structured table with
columns for common values such as time & event name. You will quickly become familiar with the EventData
column, which contains the full original JSON payload and is useful in almost all queries. You can read the
following documentation on the events.all table.
The anatomy of a query
A query expression most commonly begins with the name of the table. This is followed by the pipe delimiter (|).
Next comes one or more operators. Each operator is separated by the pipe delimiter.

As a matter of preference, a query can be expressed on a single line or using a line return before each pipe
delimiter. It makes no difference to the query itself.

The Query pane can contain more than one query. This makes it easy to start with a simple expression, validate
it runs, and build on it.
A blank line will separate one query from another. Your cursor position determines which query will run when
you press the “Run” button. You can also highlight a portion of the query to run only that expression.

Building Your first query


Now let’s author your first query from scratch. You can type the table name into the Query pane. But we’re
going to use a little shortcut. Find the events.all table in the Resources pane. You may have to expand your
title ID database by clicking the arrow.

Once you’ve located the events.all table, double click the table name. You’ll notice this expression has been
added to the Query pane.

NOTE
In Preview, you'll need to manually add the brackets and single quotes around the table name. A fix for this inconvenience
is in progress.

['events.all']
|

Note the brackets and single quotes around the name. Whenever the table or column name includes a “.” these
are required. Your cursor is now in the correct position to author your first operator. Let’s start using the take
operator.
['events.all']
| take 100

Run this query. Note that the Results pane now shows 100 rows of raw data.
In the Results pane, click the top row. Using the right arrow, navigate over to the FullName_Name column. This is
the name of the event. Arrow down until you find a player_logged_in event. Once you’ve found one, right arrow
over to the EventData column and double click. You should now see this:

Your query can reference any properties in the EventData JSON using the dot notation (.). You can try this now
by modifying your query to return only player_logged_in events from a single player. Double-click the EntityID
GUID and copy it to the clipboard.
Now update your query as follows and insert the GUID you copied:

['events.all']
| where FullName_Name == 'player_logged_in'
| where Entity_Id == 'paste from clipboard here'

TIP
Double equal signs are used to evaluate string equivalency. Single quotes at the beginning and end set apart a string.

Run the query and you’ll see the Results pane show player_logged_in events only for the selected player. You
can use dot notation to reference multiple nested layers of JSON hierarchy by simply adding a dot between each
layer.
Now let’s create a second query to group player logins by region. Without deleting what you’ve written, press
return twice. Let’s add a comment to our next query by using “//”. Comments will not be executed and are
helpful to keep track of the intent behind each query.

//Player logins by platform

Once again, double-click the events.all table from the resources pane. This time, let’s add a time delimiter to our
expression to scope our query to just the past three days.

//Player logins by platform


['events.all']
| where Timestamp > ago(30d)
| where FullName_Name == 'player_logged_in'

Run this query to get a full list of all log-in events over the past three days. However, we want to know how
many distinct players have logged in, not the count of events. To do this, we’ll use the distinct operator by Entity
ID.

['events.all']
| where Timestamp > ago(3d)
| where FullName_Name == 'player_logged_in'
| distinct Entity_Id

This query returns a list of Entity IDs who’ve logged in during the past three days. The Results pane shows the
number of records, so we can see the total count.

Now let’s get the count of players who’ve logged in from each platform. To do this, we’ll need the distinct count
of Entity IDs grouped by the platform property in the EventData JSON. This requires the summarize operator.
Because summarize does not support dynamic types, we’ll also need to cast platform to a string.

['events.all']
| where Timestamp > ago(3d)
| where FullName_Name == 'player_logged_in'
| summarize dcount(Entity_Id) by tostring(EventData.Platform)

Let’s finish this off with a flourish. By adding a single additional expression, we can render our results as a
column chart.

['events.all']
| where Timestamp > ago(3d)
| where FullName_Name == 'player_logged_in'
| summarize dcount(Entity_Id) by tostring(EventData.Platform)
| render columnchart
Sample Queries
We’ve only just scratched the surface of the types of queries that can be authored in Explorer. More example
queries can be loaded from the Explorer page by pressing “What’s This”. Each of these sample queries is chosen
to demonstrate some of the various operators available and how they can be applied to real world questions.

NOTE
Because the shape of your data might vary from our demo data set, you may need to modify the sample query to run for
your scenario.

Limits
There are two limits which govern Explorer query usage:
1. Max query runtime: An individual query is not permitted to run longer than 30 seconds. If this limit is
exceeded, the query will be terminated and you will receive an error message.
2. Interval Usage: Each title is permitted a cumulative total runtime of three minutes per any given 10
minute interval. If this limit is exceeded, you will receive an error message and will need to wait before
running additional queries.

Data Retention
By default, Data Explorer queries run on hot storage, which can be configured in the Management tool. Queries
that search beyond the data stored in hot storage will have significantly longer run times and may time out.
Schemas
5/24/2022 • 2 minutes to read • Edit Online

NOTE
The Explorer Feature is in public preview. We anticipate ongoing changes to it as we continue gathering feedback and
optimizing for customer use.

Overview
This section describes the data and data products stored in PlayFab Insights, an in-development offering
designed to provide a complete backend solution for data and analytics. For more information on the PlayFab
Insights vision and strategy, see our webinar.
Out of the box, PlayFab Insights offers a database for every title. This database contains tables with all the event
and processed data generated by your title. At a high level, data comes in two forms:
1. Event data streamed by the game and game services or the PlayFab APIs.
2. Processed data generated by PlayFab and its services on a scheduled basis.
Learn more about how to get started in the Quickstart section.
Schemas quickstart
5/24/2022 • 2 minutes to read • Edit Online

NOTE
The Schemas Features are in public preview. We anticipate ongoing changes to it as we continue gathering feedback and
optimizing for customer use.

Event Data
Event Data arrives in Insights through one of several pathways:
Many API calls log events which are automatically written to PlayFab Insights. For example, the
player_logged_in event is generated each time a log in API call is made.
The WriteEvents API allows developers to send descriptive events.
The WriteEvents.
Each of these events lands in a single table called events.all.

Processed Data
NOTE
No processed data sets are available in PlayFab Insights at this stage of our Public Preview. Please check back over time as
new features become available.

Processed data is copied into your title's database on a scheduled basis as transforms occur. Examples include
the Trends table, which is calculated nightly in order to power the Trends feature on Game Manager. This data is
copied to your Insights database for to enable custom analysis. Other planned data sets include the Player
Profile state table.
Schemas Tutorials
5/24/2022 • 2 minutes to read • Edit Online

The following tutorials introduce the schemas available in PlayFab Insights.


events.all
About the events.all table
5/24/2022 • 2 minutes to read • Edit Online

The events.all table is the destination for all incoming events regardless of the ingestion pipeline they come
through. This table powers several features on Game Manager, including Event History and Explorer.

NOTE
Many columns present are written as an artifact of our ingestion process and are in the process of being deprecated. Only
those listed below are intended to remain. Other columns can and should be disregarded.

C O L UM N N A M E DATA T Y P E DESC RIP T IO N

SchemaVersion String Indicates the schema version assigned


to the event by the PlayFab services.
This number will increment when
structural changes occur to the event.

FullName_NameSpace String A namespace assigned to the event in


ingestion. Designed to prevent
collisions between title telemetry
events and PlayFab events of the same
name. Useful for grouping by domain.

FullName_Name String The name of the event.

Entity_Id String The unique id of the entity sending the


event, i.e. title player, character, title,
etc.

Entity_Type String The type of entity sending the event,


i.e. title player, character, title, etc.

EntityLineage_title String The Title ID from which the event


occurred.

EventData Dynamic The original JSON payload of the


event.

EventId String A unique GUID identifier for each


event.

Timestamp DateTime The time the event was received by


PlayFab.

EntityLineage_title_player_account String The title player id associated with the


event. For more information, see
Available built-in entity types.

EntityLineage_master_player_account String The master player id associated with


the event. For more information, see
Available built-in entity types.
C O L UM N N A M E DATA T Y P E DESC RIP T IO N

EntityLineage_namespace String The namespace associated with the


event. For more information, see
Available built-in entity types.
Insights Management: Performance Levels &
Retention
5/24/2022 • 5 minutes to read • Edit Online

PlayFab Insights provides studios the ability to change the performance characteristics of their data system.
Controls are located in Management under the data section in Game Manager.

Performance Levels
Why are performance levels important?
Performance levels determine
the resources (cache size, compute power, memory) given to each query
the limits of concurrent queries, max number of concurrent queries, events per second, and active event
exports
Performance levels can also be used to increase the max number of events per second and the number of
allowed active event exports for a title.
How can I change my performance level?
The Performance Level slider is used to select a new performance level. The Performance Level Settings table
shows a comparison of your current settings versus new settings you've selected:

Is performance level access limited?


Yes. Every titles begins at Performance Level 1, a free tier of service that is included in all PlayFab offerings. Live
titles can change their performance level at will, however, titles in Development Mode must either enable paid
insights features or launch to access performance levels greater than 1.
To enable paid Insights features while a title is in development mode:
1. Log in to PlayFab.com
2. Select a title in Development Mode to enter the Title Overview page
3. Navigate to the "Data" tab on the left-hand side of the page
4. Navigate to the "Management (Preview)" tab on the top of the page
5. In the banner, select "Enable" to enable paid Insights features
If a payment method is missing from your account, you will need to add one in order to access paid Insights
tiers. To do this, select "Add credit card" on the page's banner which will take you to the billing information page.
Once a payment instrument is added, the Insights Management page will allow you to enable paid Insights
features as described.

NOTE

Once paid insights features are enabled for a title, that title will also have access to customized data retention
values.
Cache Size
PlayFab Insights uses a specialized variation of Azure Data Explorer (Kusto). Insights separates storage into two
categories: Hot Cache and Storage. Hot Cache is memory and SSD storage and is extremely fast to query.
Complex queries and data functions are executed quickly when all data is readily accessible in the hot cache.
Data stored outside the hot cache in storage is still easily accessible and can be queried, but query times may
slow down with large datasets in storage. Data is separated by ingestion time, the most recent data stored first
in hot storage. Data storage is an entirely internal process to Insights and data is accessed in the same manner
no matter where its stored.
Example:
A studio has selected performance level 3 and therefor has 100GB of cache. They have also select 1200 days of
retention, so there is just over 3 years of data stored in their cluster. If the studio has a daily data footprint of 1
GB a day, then 100 Days of data is stored in the hot cache. A user can run a query over 90 days and query only
hot cache, they can run that same query over all 3 years and query from both sources, no change is needed in
query structure.
How is cache affected when I change my performance level?
When you change your performance down, data is loaded from hot cache into storage as the hardware
resources are reduced. Similarly, when increasing your performance level, hardware is instantly allocated to you
and data is transfered into your cache. This process is generally very fast, but terabyte level shifts in cache size
can take a short time to complete. For more information see Best Practices.
Compute Power
Compute power represents the maximum quantity of vCPUs allocated for each query. Based on the
parallelization of a given query plan, some queries cannot take full advantage of all vCPUs at once (order,
distinct). Additionally, to improve interactivity of the querying experience, priority is given to queries by start
time, meaning subsequent concurrent queries may see decreased vCPU allocation.
Compute power also increases the maximum query length before timeout. the following table represents
current numbers:

C O M P UT E P O W ER M A XIM UM C O M P UT E T IM E ( SEC O N DS)

2 (Free Tier) 30s


C O M P UT E P O W ER M A XIM UM C O M P UT E T IM E ( SEC O N DS)

2 (Performance Level 2) 60s

4 120s

8 180s

16 210s

32 240s

48 270s

64 300s

Max Memory Per Query


This represents the total memory allocated to the query. Note this is different than the memory for storing data.
Query memory is specifically for storing query data for computation and processing, this is an important
resource for more complex queries.
Max Concurrent Queries
This value represents the amount of simultaneous queries that can run at each performance level.
Max Events Per Second
The total maximum events per second that the data system can ingest. This number is a combination of your
Playstream and telemetry events and any external ingestion that might be taking place.
What happens if I exceed my row write limit?
Paid titles are charged an overage fee of 1 Credit for every 2.7m (2,700,000) extra events ingested. This overage
cost is designed to allow customers with predictable ingestion loads to sit at a smaller performance levels
during off hours for cost savings.
Event Exports
Event Archives allow customers to export all or some of their data on a regular schedule to Azure Blob or AWS
S3. For more information, see Exporting Data.
Credits Per Hour
Insights is billed per minute at the credits per hour rate (Credits Per Hour / 60). For more information about
Insights Credit Pricing, see PlayFab Pricing.

Retention
The retention setting allows a studio to set the total number of days data is kept. The default setting is 30 days,
which fulfills most GDPR compliance regulations. Retention can be set globally or by table using Management
Commands. Retention is charged at a rate of 50 credits per terabyte month, studios are only charged for what is
in use by day. For more information about Insights Credit Pricing, see Insights Credit Pricing.
Example A studio has 10 terabytes of data stored at the beginning of the month and does not increase that
storage. The total cost would be 500 (10 TB * 50 credits/TB) Credits.
Example A studio begins the month at 250 GB of data and increases to 750 GB of data throughout the month
linearly. The total charge would be 25 (average of each day of the month 0.5 TB * 50 credits/TB) Credits.
Insights Scheduled Scaling
5/24/2022 • 2 minutes to read • Edit Online

The Insights Performance Level can be set to scale up and down at specific times of the day. This allows a studio
to match their analytics resources demand to their supply and optimize costs. Scheduled Tasks can be found
under automation in Game Manager. It can also be reached by clicking the Add Insights scaling scheduled task
button in Insights Management.

To create a task for scaling your cluster:


1. Provide a name and description for the task.
2. Select the type "Insights scheduled scaling".
3. Select the performance level you wish to scale to.
4. Select "recurring" on the right under "SCHEDULE" and provide a valid cron expression
5. Select Save at the bottom.
The scheduled scale will appear in the scheduled tasks section as well as in the Insights Management Page. The
task can be deactivated without deleting if you do not want it to run, but also do not want to delete it.
Recommendation
Changing your performance level allocates hardware resources to your data system immediately. However,
transferring data into your new resources can take several minutes. It is not recommended that you schedule
large changes in performance level quickly after previous changes. See Best Practices for recommendations.
Exporting Data
5/24/2022 • 2 minutes to read • Edit Online

Event Export is the primary mechanism for exporting data from your Insights data cluster without querying.
Event Export can be reached under the data section of PlayFab Game Manager. The amount of distinct export
commands you can run is tied to your performance level.
To create a new export:
1. Navigate to the Event Export page.
2. Select "New Event Export".
3. Fill out the required fields with your external storage account information.
4. There are several options for which data to export to choose from
a. You may select the checkbox for all events, this will export all data.
b. You may select one more more tables to export
c. You may select to use a custom query to define the output of the export. NOTE Using a custom query
for exporting all data will result in a slight addition of columns from the ETL process. NOTE When
using custom query, the output must have a timestamp column named timestamp.
5. You can choose between once an hour and once a day for export frequency
6. You can choose to have your data partitioned into individual files for more efficient storage and loading
Use Cases
1. Export all data to be ingested into a separate data system. Exporting all data allows for an efficient way to
create files to save for cold storage or for ingestion into another data processesing system. While this is
functional it is not the intended use case for Insights and Export. PlayFab Insights is excellent at data
modification and tranformation, the second case is recommended over this case.
2. Export custom query data. Using a custom query allows you to select custom datasets for export. This is ideal
for loading cleaned data models into machine learning systems like Spark and pandas (python), or into other
data systems and visualization platforms that provide specialized use cases.
Continuous Export
Continuous data export will begin exporting data only from the point of the export's creation.
Insights Management Commands
5/24/2022 • 4 minutes to read • Edit Online

Insights management commands allow users express more control over or to gather additional information on
their data system. The commands fall into two primary categories:
1. Management - These commands allow users to view more information about queries, commands and
retention as well as alter retention
2. Data Control - These commands allow users to create and drop custom tables, ingest local and cloud data
and purge data from their DB
Some commands are not available in evaluation mode.

C AT EGO RY C O M M A N DS

Management .show queries


.show running queries
.show commands-and-queries
.show table policy retention
.alter table policy retention

Data Control .create table


.drop table
.set
.append
.set-or-append
.set-or-replace
.ingest into table
.purge table

Management
.show queries
Returns a list of currently-executing queries by the user, or by another user, or by all users.
Usage: .show queries
Example: .show queries | where StartedOn > ago(1d)
This shows all queries that executed in the last day
.show running queries
Shows all currently executing queries
Usage: .show running queries
Example: .show running queries
This shows all currently running queries.
.show database policy caching
Shows the current caching policy on the database
Usage: .show database DatabaseName policy caching
Example: .show database myDatabase policy caching
This shows the current caching policy for the specified database.
.show table policy caching
Shows the current caching policy on the table
Usage: .show database DatabaseName.TableName policy caching
Example: .show database myDatabase.myTable policy caching
This shows the current cachingt policy for the specified table.
.show commands-and-queries
Returns a table with admin commands and queries which have reached a final state. These commands and
queries are available to query for 30 days.
Usage: .show commands-and-queries
Example: .show commands-and-queries | where StartedOn > ago(1d) | where State != "Completed"
This Shows all commands and queries that failed in the last day
.show table policy retention
Shows tables' effective retention policy taking cluster and database rules into account
Usage: .show table(s) (<table_name> [, ...]) policy retention
Example: .show table ['events.all'] policy retention
This shows the current retention policy for the "events.all" table.
.alter table policy retention (restricted to accounts on consumption pricing model)
Change the current retention policy on table(s) to <retention_policy>
Usage: .alter tables (<table_name> [, ...]) policy retention <retention_policy>
Example: .alter table ['events.all'] policy retention softdelete = 90d
This sets data in the "events.all" table to be removed from the table after 90 days.

Data Control
.create table (restricted to performance level 2 and above)
Creates a new empty table. The command must run in context of a specific database. If the table already exists
the command will return success.
Usage: .create table TableName ([columnName:columnType], ...)
Example: .create table ['custom.logs'] (Level:string, Timestamp:datetime, Id:string, Message:string)
This creates a new table called "custom.logs" with four columns. IMPORTANT Custom tables must begin
with "custom.".
.drop table (restricted to performance level 2 and above)
Drops the specified table. Note: This cannot be undone.
Usage: .drop table TableName [ifexists]
Example: .drop table ['custom.logs']
This drops the table named "custom.logs".
.set (restricted to performance level 2 and above)
Creates a table with results of Query Or Command
Usage: .set TableName [with (PropertyName = PropertyValue [, ...])] <| QueryOrCommand
Example: .set [‘custom.recentEvents’] <| [‘events.all’] | where Timestamp > now() – time(1h)
This creates a table "custom.recentEvents" containing the results of the above query
.append (restricted to performance level 2 and above)
Appends an existing table with results of QueryOrCommand
Usage: .append TableName [with (PropertyName = PropertyValue [, ...])] <| QueryOrCommand
Example: .append [‘custom.recentEvents’] <| [‘events.all’] | where Timestamp > now() – time(1h)
This adds to existing table "custom.recentEvents" with the results of the above query
.set-or-append (restricted to performance level 2 and above)
Create or appends to a table with results of QueryOrCommand
Usage: .set-or-append TableName [with (PropertyName = PropertyValue [, ...])] <| QueryOrCommand
Example: .set-or-append [‘custom.weekEvents’] <| [‘events.all’] | where Timestamp > now() – time(7d)
This appends data from the above query to table "custom.weekEvents". If the table does not exist, create it.
.set-or-replace (restricted to performance level 2 and above)
Replaces the data of the table if it exists (drops the existing data shards), or creates the target table if doesn't
already exist. The table schema will be preserved unless one of extend_schema or recreate_schema ingestion
property is set to true. If the schema is modified, this happens before the actual data ingestion in its own
transaction, so a failure to ingest the data doesn't mean the schema wasn't modified.
Usage: .set-or-replace TableName [with (PropertyName = PropertyValue [, ...])] <| QueryOrCommand
Example: .set-or-replace [‘custom.dayEvents’] <| [‘events.all’] | where Timestamp > now() – time(1d)
This replaces the data in table "custom.dayEvents" with the above query.
.ingest into (restricted to performance level 2 and above)
Ingests data into a table by "pulling" the data from one or more cloud storage artifacts.
Usage:
.ingest into table TableName SourceDataLocator [with ( IngestionPropertyName = IngestionPropertyValue [, ...]
)]
Example: .ingest into table [‘custom.myData’] (h’<your url here>’) with(ignoreFirstRecord=true)
This pushes data into table "custom.myData" from your cloud storage listed in the url.
.purge table (restricted to performance level 2 and above)
Permanently deletes data in table from the database
Usage: .purge table [TableName] in database [DatabaseName] allrecords with (noregrets='true')
Example: .purge table [‘custom.toPurge’] in database MyDatabase allrecords
This purges all data from table "custom.toPurge", permenantly deleting it from your data system.
Insights Pricing
5/24/2022 • 3 minutes to read • Edit Online

The total combined usage of Insights features are billed in a virtual currency called "Insights Credits". Insight
Credits are derived from conversion rates for usage of each Insight services.
The Standard and Premium pricing plans include a number of free monthly Insights credits. If usage exceeds the
number of free credits, any additional credits are billed at the rate specified on your plan. The Pay-as-you-go
pricing plan does not include free credits, so each credit is billed at the rate specified in the plan. For more
information on the number of free credits and additional credit rates included in each plan, see PlayFab Pricing.

Insights Performance
Each title is set to a chosen performance level that is billed to the minute (Insights Credits Per Hour / 60). The
cost in credits for each performance level is located at the bottom of the table on the Insights Management
page:

IMPORTANT
All MAU-based pricing plans will be converted to a usage-based pricing plan on 11/01/2020. As part of the transition, a
small number of titles will be placed on a paid Insights Performance level to maintain their current functionality. However,
if a title would like to reduce the performance level (and thus cost) while also accepting a decrease in performance, the
performance level can be adjusted on the Insights Management page in Game Manager using the above table.

Retention
Data retention is billed in Terabyte months. Every day the end of day storage size is recorded and averaged over
the month. Each terabyte is billed at 50 credits per terabyte month. For example, if a studio stored 1 terabyte of
data every day for a month, the total would be 1 TB/Month * 50 Credits = 50 Credits.
Pricing example
Below is an example scenario illustrating how one month of Insights billing is calculated for a studio:
In April, a studio used performance level 4 from 9AM to 5PM each weekday and scaled down to performance
level 2 at nights and on weekends. April has 21 weekdays and 9 weekend days, which works out to:
21 days at performance level 4, for 8 hours
21 days at performance level 2, for 16 hours
9 days at performance level 2, for 24 hours
The credit rate per hour for each of these levels is:
performance level 2 = 1 credits/hour
performance level 4 = 4 credits/hour
The total monthly charge for Insights Performance is calculated as:
21 (days) * 8 (hours) * 4 (credits per hour at performance level 4) + 21 (days) * 16 (hours) * 1 (credits per hour
at performance level 2) + 9 (days) * 24 (hours) * 1 (credits per hour at performance level 2) = 1,224 credits for
the month.
Starting the month with no stored data, the studio added 1 TB of data every other day for 30 days. At the end of
the month they averaged 15 TBs of data over the month. The total monthly charge for data retention is
calculated as:
15 TB * 50 Credits per TB/month = 750 Credits for the month.
Thus, the studio's total monthly cost for Insights performance and data retention is 1,974 credits.

Row Write Overages


Each Insights Performance level has an allotted number of writes per second to the data cluster. For customers
not in development mode, going beyond the number of row writes for your performance level triggers row
write overages instead of event throttling. Row write overages are charged at 1 credit per 2.7 million (2,700,000)
rows written. This pricing is designed to allow for specific ingestion scenarios where it may be more cost
effective to have row write overages instead of raising the Insights performance level.
Best Practices & FAQ
5/24/2022 • 8 minutes to read • Edit Online

Here we examine some best practices for using PlayFab Insights as well as address the most frequently asked
questions.

Best Practices
Each performance level comes with a certain quantity of cache. It is a good idea to calculate a daily data
footprint and decide how many days of data you would like in cache. A small buffer or very well known
data footprint will allow anyone performing queries to know when to expect optimal performance.
Running visualizations against that expected performance is also recommended for quick results.
For example, a studio has a 5 GB / day data footprint. Selecting a cache size of 450+ GB will allow 90
days of data in cache. Running all visualizations in 90 day running windows will be very efficient.
Joins, unions, and advanced queries will be very efficient. Another option would be to focus live
visualizations primarily on 30 day windows and set cache size up to 90 days during working hours
and 30 days during off hours, this will create large efficiencies in cost savings. Also keep in mind that
data is compressed in cache.
Data visualization platforms like PowerBI often run multiple queries for a single visualization. It's
recommended that the visualizations be updated serially. If under heavy load, or being used by many
users, it may make sense to increase performance level to a level that has higher concurrent queries
allowed to free up simultaneous queries for external tools and analysts.
The most common use case for scheduled scaling is to scale up during standard working hours and to
scale down after hours and weekends. If making large changes in performance level (e.g. level 3 to 8) it's
recommended that you intend to stay at the higher performance level for several hours. Loading
terrabytes of data in and out of cache quickly is an inefficient use of resources. All other limits are raised
instantly, so you may choose to make the scaling changes if needed.
Scheduled scaling is not mutually exclusive with manual scaling. If you find that you need more resources
in middle of the day, you can make a manual change, the scheduled scaling will continue as expected.
Reducing data storage can result in data loss. You will be warned with the message "Selected retention
setting is lower than current setting. Doing so may result in a loss of data." when attempting to reduce
storage. Due to the low cost of storage, long term retention is recommended.
Insights management commands allow the creation and updating of custom tables. For core reporting
and often used tables it's helpful to build custom aggregation tables. Aggregation tables generally have a
much smaller data footprint than the source data. This increases query performance and reduces the
need for a higher performance level.
For automating data aggregation we recommend using Azure Data Factory, a low-cost and scalable
automation option. For more information on using Azure Data Factory see the connectivity section.
Limit queries by timestamp, don't pull all data to explore the last several days (this is generally good
advice in any data system).

FAQ
How can I query data?
1. The simplest way is to use our built in data explorer.
2. The connectivity section has details on additional ways to access data.
I sent a Microsoft authentication link (AAD) and it didn't work, what happened?
If you already have a PlayFab account, you need to sign out before accepting an invite with a different
authentication method.
Why am I getting an error when trying to change my performance level or data retention?
1. If you have not signed up for a paid account, changing performance levels, retention, exports and some
management commands will be unavailable.
2. If your Insights cluster is currently changing performance levels you must wait until the change is completed.
Can I change between free and paid performance levels?
Sure! You can revert back to the free tier if you don't currently need any of the paid features.
How do I get data into my Insights cluster?
1. Most PlayFab services automatically generate data for you.
2. You can also implement your own telemetry through PlayStream, or our Telemetry system.
3. You can use Management Commands to ingest custom datasets.
What is the standard data schema for PlayFab events?
In PlayFab Insights we load all the data from all events into a single table. This table is named ['events.all].
Inside that table you will see a column called "EventData" that contains the payload of JSON information for
each event. For complete information about the events.all table, see About the events.all table for more
complete information.
Why can't I write SQL?
As of now, we only support KQL (Kusto Query Language) queries in most scenarios. We're actively exploring
adding SQL support. While KQL takes some getting used to, we think you'll like it once you do. For
information on converting SQL to Kusto queries, see SQL to Kusto query translation.
What's the difference between Events Per Second in my Insights performance level and the costs of sending
PlayStream events?
Events per second in your Insights performance level represents data ingestion to your cluster through any
means. PlayStream write events and write telemetry events are billed independently and represent the cost
of writing to the cloud.
Can I have a higher performance level than what I see on my management page?
File a support ticket with us and we'll contact you to arrange something that meets your needs.
What is the underlying technology behind PlayFab Insights?
PlayFab Insights uses a specialized variant of Azure Data Explorer (Kusto).
Why is my data schema different when exporting using custom queries?
The custom query output includes details from the ETL (Extract Transform Load) process. Some extra
columns will be included. Those columns are generally hidden in the query environment as they do not serve
a purpose.
What happens if I reduce my retention setting to a quantity of days that is less than the total number of days I
have data for?
You're warned that if you reduce your retention you might delete data. For example, if you have been
operating for 1 year and reduce the retention to 6 months, only the most recent 6 months of data is saved,
the rest is discarded.
How do I increase the timeout time on my queries?
The time out limits on queries is relative to your compute power which is defined in your performance level.
Refer to the compute power table in Performance and Retention under compute power.
Is there a limit to how much telemetry I can send?
The following limits exist for the WriteTelemetryEvents API call:

L IM IT N A M E L IM IT VA L UE N OT ES

Events per request 200 events per request Exceeding this limit will result in a
BadRequest error.

Events per entity 8,000 per second Exceeding this limit will result in a
PerEntityEventRateLimitExceeded
error. An entity most often
represents an individual player, but
can also be a player group or title.

Max payload size 10240 bytes (10KB)

If you run into any of these limits, please contact the Playfab Support team for assistance. In the upper
right-hand corner of Game Manager select the question mark icon, then select Contact Us .
I get an error “Query execution has exceeded the allowed limits” when I try to run a query.
This error occurs when the size of the result set or the number of rows in the result set exceeds the allowed
limit. Try limiting the amount of data returned by scoping the query to relevant data using the where, limit, or
summarize operators
To export all of your data, navigate to the Event Expor t Tab under Data on the Title Over view page in
PlayFab Game Manager.
If you want to pull only segments of data or if you are still hitting the query limit, you can partition the data
by time or unique id (ex. Player ID, Title ID) and run multiple, smaller queries. The follow is an example of how
to partition based on time:
Where

let start = datetime(2020-08-03);


let end = datetime(2020-08-07);
['events.all'] | where Timestamp between(start .. end)

Limit

['events.all'] | limit 1000

Summarize

['events.all'] | summarize count() by FullName_Name, bin(Timestamp, 1d)

View Kusto documentation for more information.


I set truncationmaxsize and truncationmaxrecords variables to a larger value, but I am still getting an error.
PlayFab Insights does not currently support setting these variables. See above for query formulation tips.
Will querying Insights data prevent events from being ingested?
No. PlayFab events will flow into your title’s database with no performance
penalty.
My queries return a “Partial query failure: Low memory condition” error
This means the query is too complex and is unable to fit within the memory limits of your Performance Level.
Try simplifying your query. For example, a summarize call may have too many groups, or you may be trying
to operate on too many rows at once.You can also upgrade your Performance level to allow more memory to
be allocated to each query.
View Kusto documentation for more information.
Will I lose data if my volume of events is higher than what is allowed by my performance level?
No, but you will be charged for overrages. Overages are measured in the number of Insights Credits
consumed. Insights Credit prices can be found on PlayFab.com/Pricing.
How do I decide by performance level?
The right performance level for you is best determined by your title's usage. By raising performance level,
you'll gain access to more data in cache and other query resources resulting in faster running queries. View
Insights documentation to learn more about performance levels.

How do I grant a user permissions to the Data > Explorer page for a
particular title?
Follow the PlayFab User Roles guide to access, create, and grant user permissions.
A user needs the following 3 permissions to access the Data Explorer:
Explorer data & tab (Read and Write permissions)
Analytics data read access (Read permissions)
Analytics data write access (Write permissions)
What are PlayFab Social Features?
5/24/2022 • 2 minutes to read • Edit Online

Adding social elements to a game helps keep players engaged and leverages your most valuable asset; your
community. No matter what form player interaction takes in your game, PlayFab can help you enable that
interaction with its suite of built-in common social gaming features.

Key Features
PlayFab Social features revolve around interactions between players, and includes friends lists, groups, clans and
guilds, tournaments, leaderboards, and support for player trading.
Friends
5/24/2022 • 2 minutes to read • Edit Online

Letting players connect with their friends is a great engagement tool for your game! PlayFab offers you the
ability to integrate with your players' existing social network (like Facebook, Steam, or Xbox Live) or to manage
your own custom friends lists within your game.
Any player in your title may be friends with any other player in your title. Notably, friendship on PlayFab is a
one-way street.
If Julie adds Bob as a friend, there is no approval process for Bob . In fact, Bob may be unaware.
Bob must separately add Julie for the friendship to be mutual.
If you wish to have reciprocity rules, it is your title's responsibility to enforce these conditions with a custom
game server or CloudScript logic, if necessary.
Friends lists
5/24/2022 • 3 minutes to read • Edit Online

Friends lists are a great feature for improving your players' ability to socialize. They're easy to work with, and
can make leaderboards more engaging for your users.

Prerequisites
SDK: Unity
The title ID is set in the PlayFabSharedSettings object.
The project can successfully log in a user.
The title has at least two registered users.

About friends
Any player in your title may be friends with any other player in your title. Notably, friendship on PlayFab is a
one-way street.
If Alber t adds Bob as a friend, there is no approval process for Bob . In fact, Bob may be unaware.
Bob must separately add Alber t for the friendship to be mutual. If you wish to have reciprocity rules, it is your
title's responsibility to enforce these conditions with a custom game server or CloudScript logic, if necessary.
In the event that a player has linked their Steam, Facebook, or Xbox Live account, their platform-specific friends
can also be displayed, if those friends also play your title.

Making friends
The example code uses the functions DisplayFriends() , and DisplayError(string error) as a proxy of your
app's UI. You paste these into your editor to get it to work without any extra effort - or replace the calls with your
own code.

void DisplayFriends(List<FriendInfo> friendsCache) { friendsCache.ForEach(f =>


Debug.Log(f.FriendPlayFabId)); }
void DisplayPlayFabError(PlayFabError error) { Debug.Log(error.GenerateErrorReport()); }
void DisplayError(string error) { Debug.LogError(error); }

1. Once a player logs in, they can access the UI for friends. The functionality usually includes adding, removing,
and displaying friends, at a minimum.
2. To get the player's current friends list, use the GetFriendsList API call.
List<FriendInfo> _friends = null;

void GetFriends() {
PlayFabClientAPI.GetFriendsList(new GetFriendsListRequest {
IncludeSteamFriends = false,
IncludeFacebookFriends = false,
XboxToken = null
}, result => {
_friends = result.Friends;
DisplayFriends(_friends); // triggers your UI
}, DisplayPlayFabError);
}

The GetFriendsList result contains a parameter friends which is a list of FriendInfo objects.
3. To add a friend to the player's friend list, use the AddFriend API call.

enum FriendIdType { PlayFabId, Username, Email, DisplayName };

void AddFriend(FriendIdType idType, string friendId) {


var request = new AddFriendRequest();
switch (idType) {
case FriendIdType.PlayFabId:
request.FriendPlayFabId = friendId;
break;
case FriendIdType.Username:
request.FriendUsername = friendId;
break;
case FriendIdType.Email:
request.FriendEmail = friendId;
break;
case FriendIdType.DisplayName:
request.FriendTitleDisplayName = friendId;
break;
}
// Execute request and update friends when we are done
PlayFabClientAPI.AddFriend(request, result => {
Debug.Log("Friend added successfully!");
}, DisplayPlayFabError);
}

4. To remove a player from a player's friends list, use the RemoveFriend API call.

// unlike AddFriend, RemoveFriend only takes a PlayFab ID


// you can get this from the FriendInfo object under FriendPlayFabId
void RemoveFriend(FriendInfo friendInfo) {
PlayFabClientAPI.RemoveFriend(new RemoveFriendRequest {
FriendPlayFabId = friendInfo.FriendPlayFabId
}, result => {
_friends.Remove(friendInfo);
}, DisplayPlayFabError);
}

Going further
There are other things you can do with friends besides adding, removing, and displaying.
Tagging friends
The FriendInfo object, retrieved from GetFriendsList, includes a list of tags for the friend. When updating the list,
you would want to add and remove from this list, and include it in the API call (as shown below).
// this REPLACES the list of tags on the server
// for updates, make sure this includes the original tag list
void SetFriendTags(FriendInfo friend, List<string> newTags)
{
// update the tags with the edited list
PlayFabClientAPI.SetFriendTags(new SetFriendTagsRequest
{
FriendPlayFabId = friend.FriendPlayFabId,
Tags = newTags
}, tagresult => {
// Make sure to save new tags locally. That way you do not have to hard-update friendlist
friend.Tags = newTags;
}, DisplayPlayFabError);
}

You can use tags to inform matchmaking (for example, the player doesn't like playing with friends tagged 2tuff
at hard difficulty), implement friend groups - or just use them to store any metadata associated with a
relationship that you need.
An important note is that PlayFab currently does not index these tags in any way. GetFriendsList can't filter
based on them, so that must be done locally.
Keep this in mind when considering any performance implications resulting from this system.
Friends Tutorials
5/24/2022 • 2 minutes to read • Edit Online

These tutorials show you how to use Friends and Groups.


Friends Leaderboards
Friends leaderboards
5/24/2022 • 2 minutes to read • Edit Online

Friends-specific APIs mirror the standard GetLeaderboard and GetLeaderboardAroundPlayer API calls, but
restrict the player pool to the player's friends list.

NOTE
The GetFriendLeaderboardAroundPlayer API does not base the center of the leaderboard around the currently logged in
player - it can be any PlayFab ID supplied with the request. You can use this to allow players to look up any friend's
location on the leaderboard, regardless of their distance from each other.
Groups, guilds and clans
5/24/2022 • 2 minutes to read • Edit Online

The Group entity type can be utilized by your game to create guild and clan interactions within your game. This
entity type gives you the ability to create different roles for members, invite members into the group, and
manage group membership.
The group that you create can utilize all of the base Entity programming model capabilities. For example, it can
use Objects and Files to store data that is specific to the Group.
To build a guild or clan system in your game, you will want to utilize the group functionality, and create a
customized experience within your game.
Entity groups
5/24/2022 • 7 minutes to read • Edit Online

PlayFab guild solution


Let's say that you need guilds, clans, corporations, companies, tribes - or whatever your game calls them -
PlayFab has them.
PlayFab builds guilds using the new Entity Programming Model, or more specifically - the entity type of groups.
Entity groups are a much broader concept than guilds, but fundamentally, entity groups have been created as a
solution for guilds.

Entity groups
Entity groups are the root concept that was inspired by the need for clans/guilds.
At its core, entity groups are any logical group of entities, which can serve any purpose. Entity groups can
simultaneously serve many purposes within your game.
Examples
Clans/Guilds - This was the starting point, and the main driving need. Entity groups can be used to
describe a set of players who are playing together on a regular basis, for whatever social glue that holds
them together on a long-term basis.
Par ties - Entity groups can be used for short-term groups created to allow individual players to
accomplish an immediate goal, and then easily disbanded afterward.
Chat Channels - Short or long term chat channels can be defined as an entity group.
In-Game subscription to information - Do you have a single-instance legendary item in your game?
Do players want constant updates about what is happening with that item? Create an entity group
focused on that item, with all player entities interested in the item as members.
In short, entity groups can be any collection of entities (whether NPC or player-controlled, real or abstract),
which need a persistent-state bound to that group.
A friends list is a group. A three person private chat is a group. Go nuts!

NOTE
We'd appreciate some warning in the forums if you are trying something we might not be expecting...

In addition, since entity groups are also entities themselves, they will contain all the initial features of entities:
Object data
File data
Profiles
They will be generally eligible for new entity features going forward, if those features are relevant to groups.

Using entity groups


Today, entity groups can contain players and/or characters. When creating a group, the first entity added to the
group is placed in an Admin role (this guide will refer to that entity as the owner, for simplicity). The owner will
then be able to invite new members, create new roles with a wide variety of customizable permissions, modify
member roles, kick members, etc.
Additionally, the same entity functions that exist for entities also function for groups, so you will be able to save
JSON objects and files directly to the group to save arbitrary game-specific data.
The code example that is provided below should give you a head start on basic guild interaction.
It allows you to create groups, add and remove members, and delete the group. It is meant to be a starting
point, and does not demonstrate any of the roles or permissions.

using PlayFab;
using PlayFab.GroupsModels;
using System;
using System.Collections.Generic;
using UnityEngine;

namespace TestGuildController
{
/// <summary>
/// Assumptions for this controller:
/// + Entities can be in multiple groups
/// - This is game specific, many games would only allow 1 group, meaning you'd have to perform some
additional checks to validate this.
/// </summary>
[Serializable]
public class GuildTestController
{
// A local cache of some bits of PlayFab data
// This cache pretty much only serves this example , and assumes that entities are uniquely
identifiable by EntityId alone, which isn't technically true. Your data cache will have to be better.
public readonly HashSet<KeyValuePair<string, string>> EntityGroupPairs = new
HashSet<KeyValuePair<string, string>>();
public readonly Dictionary<string, string> GroupNameById = new Dictionary<string, string>();

public static EntityKey EntityKeyMaker(string entityId)


{
return new EntityKey { Id = entityId };
}

private void OnSharedError(PlayFab.PlayFabError error)


{
Debug.LogError(error.GenerateErrorReport());
}

public void ListGroups(EntityKey entityKey)


{
var request = new ListMembershipRequest { Entity = entityKey };
PlayFabGroupsAPI.ListMembership(request, OnListGroups, OnSharedError);
}
private void OnListGroups(ListMembershipResponse response)
{
var prevRequest = (ListMembershipRequest)response.Request;
foreach (var pair in response.Groups)
{
GroupNameById[pair.Group.Id] = pair.GroupName;
EntityGroupPairs.Add(new KeyValuePair<string, string>(prevRequest.Entity.Id,
pair.Group.Id));
}
}

public void CreateGroup(string groupName, EntityKey entityKey)


{
// A player-controlled entity creates a new group
var request = new CreateGroupRequest { GroupName = groupName, Entity = entityKey };
PlayFabGroupsAPI.CreateGroup(request, OnCreateGroup, OnSharedError);
PlayFabGroupsAPI.CreateGroup(request, OnCreateGroup, OnSharedError);
}
private void OnCreateGroup(CreateGroupResponse response)
{
Debug.Log("Group Created: " + response.GroupName + " - " + response.Group.Id);

var prevRequest = (CreateGroupRequest)response.Request;


EntityGroupPairs.Add(new KeyValuePair<string, string>(prevRequest.Entity.Id,
response.Group.Id));
GroupNameById[response.Group.Id] = response.GroupName;
}
public void DeleteGroup(string groupId)
{
// A title, or player-controlled entity with authority to do so, decides to destroy an existing
group
var request = new DeleteGroupRequest { Group = EntityKeyMaker(groupId) };
PlayFabGroupsAPI.DeleteGroup(request, OnDeleteGroup, OnSharedError);
}
private void OnDeleteGroup(EmptyResponse response)
{
var prevRequest = (DeleteGroupRequest)response.Request;
Debug.Log("Group Deleted: " + prevRequest.Group.Id);

var temp = new HashSet<KeyValuePair<string, string>>();


foreach (var each in EntityGroupPairs)
if (each.Value != prevRequest.Group.Id)
temp.Add(each);
EntityGroupPairs.IntersectWith(temp);
GroupNameById.Remove(prevRequest.Group.Id);
}

public void InviteToGroup(string groupId, EntityKey entityKey)


{
// A player-controlled entity invites another player-controlled entity to an existing group
var request = new InviteToGroupRequest { Group = EntityKeyMaker(groupId), Entity = entityKey };
PlayFabGroupsAPI.InviteToGroup(request, OnInvite, OnSharedError);
}
public void OnInvite(InviteToGroupResponse response)
{
var prevRequest = (InviteToGroupRequest)response.Request;

// Presumably, this would be part of a separate process where the recipient reviews and accepts
the request
var request = new AcceptGroupInvitationRequest { Group = EntityKeyMaker(prevRequest.Group.Id),
Entity = prevRequest.Entity };
PlayFabGroupsAPI.AcceptGroupInvitation(request, OnAcceptInvite, OnSharedError);
}
public void OnAcceptInvite(EmptyResponse response)
{
var prevRequest = (AcceptGroupInvitationRequest)response.Request;
Debug.Log("Entity Added to Group: " + prevRequest.Entity.Id + " to " + prevRequest.Group.Id);
EntityGroupPairs.Add(new KeyValuePair<string, string>(prevRequest.Entity.Id,
prevRequest.Group.Id));
}

public void ApplyToGroup(string groupId, EntityKey entityKey)


{
// A player-controlled entity applies to join an existing group (of which they are not already a
member)
var request = new ApplyToGroupRequest { Group = EntityKeyMaker(groupId), Entity = entityKey };
PlayFabGroupsAPI.ApplyToGroup(request, OnApply, OnSharedError);
}
public void OnApply(ApplyToGroupResponse response)
{
var prevRequest = (ApplyToGroupRequest)response.Request;

// Presumably, this would be part of a separate process where the recipient reviews and accepts
the request
var request = new AcceptGroupApplicationRequest { Group = prevRequest.Group, Entity =
prevRequest.Entity };
prevRequest.Entity };
PlayFabGroupsAPI.AcceptGroupApplication(request, OnAcceptApplication, OnSharedError);
}
public void OnAcceptApplication(EmptyResponse response)
{
var prevRequest = (AcceptGroupApplicationRequest)response.Request;
Debug.Log("Entity Added to Group: " + prevRequest.Entity.Id + " to " + prevRequest.Group.Id);
}
public void KickMember(string groupId, EntityKey entityKey)
{
var request = new RemoveMembersRequest { Group = EntityKeyMaker(groupId), Members = new
List<EntityKey> { entityKey } };
PlayFabGroupsAPI.RemoveMembers(request, OnKickMembers, OnSharedError);
}
private void OnKickMembers(EmptyResponse response)
{
var prevRequest= (RemoveMembersRequest)response.Request;

Debug.Log("Entity kicked from Group: " + prevRequest.Members[0].Id + " to " +


prevRequest.Group.Id);
EntityGroupPairs.Remove(new KeyValuePair<string, string>(prevRequest.Members[0].Id,
prevRequest.Group.Id));
}
}
}

Deconstructing the example


This example is built as a controller, which saves minimal data to a local cache (PlayFab being the authoritative
data layer), and provides a way to perform CRUD operations on groups.
Let's take a look at some of the functions in the example provided:
OnSharedError - This is a typical pattern with PlayFab examples. The simplest way to handle an error is to
report it. Your game client will probably have much more sophisticated error handling logic.
ListMembership - This calls ListMembership to determine all the groups that the given entity belongs to.
Players will want to know the groups they have already joined.
CreateGroup / DeleteGroup - Mostly self-explanatory. This example demonstrates updating the local
group info cache when these calls are executed successfully.
InviteToGroup / ApplyToGroup - Joining a group is a two-step process, and it can be activated both
directions:
A player can ask to join a group.
A group can invite a player.
AcceptGroupInvitation / AcceptGroupApplication - The second step of the join process. The responding
entity accepts the invitation, completing the process of making the player a part of the group.
RemoveMembers - Members with authority to do so (defined by their role permissions), will be able to kick
members from a group.

Server vs client
Like all new entity API methods, there is no distinction between the server API and the client API.
The action is performed by the caller, according to how the process was authenticated. A client will be identified
as such, and will call these methods as a title player entity, and their roles and permissions within the group will
be evaluated with every call, ensuring they have permission to perform this action.
A server is authenticated with the same developerSecretKey , which identifies that process as a title entity. A title
will bypass the role checks, and API calls executed by a title will only fail if the action is impossible to perform, in
an instance such as if an entity cannot be removed if they are not a member.
Groups, guilds, and clans tutorials
5/24/2022 • 2 minutes to read • Edit Online

These tutorials teach you how to use groups functionality for your games, and how to build guilds and clans
within your game.
To store data for your groups, guilds or clans:
Objects
Files
For turn based games:
Using Shared Group Data
Using Shared Group Data
5/24/2022 • 3 minutes to read • Edit Online

Shared Group Data is a simple way for players to share some information with a tightly constrained list of other
players.

NOTE
Shared Group Data was originally designed to be driven by server-authoritative for most cases, and the previous advice
was to not add players directly to the Shared Group data, as that gave them read/write permissions (allowing for
cheating). However, our new API Access Policy allows a much greater variance in functionality and security over the
original design. More details are available in the advanced section of this document.

WARNING
Shared Group Data should not be used by groups larger than a dozen or so players, at most. One issue is that too many
players attempting to read the same data at the same time will result in delays reading the data (Shared Group Data is
not sharded or cached, the way that data meant to be read by many players at once, like Title Data is). And special care
should be taken to prevent players from over-writing each others data. In the instance that multiple players try to write
to the same Key at the same time, only one of those writes will "win", resulting in the loss of the other user's data.

Example: Turn-based multiplayer Async games


The original, and still best, use case for Shared Group data is best described as storing state for an online board
game. players take turns modifying the data via CloudScript, with a clear turn order.
Players can log off and resume play later, with their game state stored in the cloud.
The following CloudScript example is the turn-based structure for any common board game. The board game
itself is stubbed out as pseudo-code.
Assumptions
The Shared Group Data that represents the game has already been started, and its membership is already
defined.
// CloudScript/Javascript
const MY_GAME_GROUP_KEYS: Array<string> = ["gameState", "currentPlayerTurn"];
interface PlayerTurnArgs {
sharedGroupId: string;
nextPlayerTurn: string;
turnData: any;
}
handlers.TakePlayerTurn = function (args: PlayerTurnArgs) {
var getRequest: PlayFabServerModels.GetSharedGroupDataRequest = { SharedGroupId: args.sharedGroupId,
GetMembers: true, Keys: MY_GAME_GROUP_KEYS };
var gameData: PlayFabServerModels.GetSharedGroupDataResult = server.GetSharedGroupData(getRequest);
CheckValidPlayer(currentPlayerId, args.sharedGroupId, gameData.Members,
gameData.Data["currentPlayerTurn"].Value, args.nextPlayerTurn);
var newGameStateJson = UpdateGameState(args.turnData, gameData.Data["gameState"].Value);
var updateRequest: PlayFabServerModels.UpdateSharedGroupDataRequest = {
SharedGroupId: args.sharedGroupId,
Data: {
"gameState": newGameStateJson,
"currentPlayerTurn": args.nextPlayerTurn
}
};
server.UpdateSharedGroupData(updateRequest);
}
function CheckValidPlayer(playFabId: string, sharedGroupId: string, members: Array<string>,
currentPlayerTurn: string, nextPlayerTurn: string): void {
var validCurPlayer = false;
var validNextPlayer = false;
for (var m = 0; m < members.length; m++) {
if (members[m] === playFabId)
validCurPlayer = true;
if (members[m] === nextPlayerTurn)
validNextPlayer = true;
}
if (!validCurPlayer || !validNextPlayer) // Take extreme action against a player trying to cheat
{
server.BanUsers({ Bans: [{ PlayFabId: playFabId, Reason: "Trying to play a game you don't belong to:
" + sharedGroupId }] });
throw "You have been banned";
}

if (playFabId !== currentPlayerTurn)


// May wish to additionally implement a spam-counter here and potentially take more extreme action
for high-spam count
throw "Not your turn";
}
function UpdateGameState(turnData: any, currentState: string): string {
// PSEUDO-CODE-STUB: Update the turn-based game state according to the rules of this game
return JSON.stringify({});
}

At a high level, you can use Shared Group Data to implement Parties/Raids, or other semi-permanent groups of
players, as long as group size is relatively small, as stated.
While there's no strictly enforced limit currently, usage with many players is not supported, and in extreme cases
may result in throttling of the title feature to prevent impact to others in the service.
Key restrictions
Shared Group Data :
Only contains simple Key/Value Pair data (strings). For use as any other data type (such as Inventory
items, Statistics, Virtual Currency, etc.), the title must provide any necessary conversions.
Is neither sharded nor cached, so it will not be responsive when accessed simultaneously by multiple
players. Features using it should be designed with small player groups in mind, and not allow for
simultaneous writes.
Client permission concerns
There is no role/rank system within a group, meaning any member in the group has absolute authority within
the group (there is no defined leader).
Bluntly, what this means is that unless you disable the Client Shared Group Data methods with our API Access
Policy, the clients will have complete control of the data, which could result in exploitation of the data.
Best practice is to either not use Shared Group Data for gameplay-impacting data, or to disable the Shared
Group Data methods in the Client API.
Leaderboards
5/24/2022 • 2 minutes to read • Edit Online

Using event or tournament leaderboards are great ways of increasing engagement within your game. Using
PlayFab, you can easily set up a recurring tournament that awards prizes to the winners, reaches out to the
participants, and gets your players coming back into your game to try and get the highest score.

What are Leaderboards?


Leaderboards are essentially rankings of entities such as players, groups, or items. A leaderboard ranks a list of
entities based on their respective values. For example, “High Scores” is one of the most common
implementations of leaderboards.

Why Use Leaderboards?


Leaderboards encourage competition among players of your game, and create incentives for the players to get
better at the game. Adopting leaderboards allows players to keep up with each other and facilitates building a
community. It can also result in players spending more time with the game and higher retention.

Tournaments
Designing your tournament
When creating your tournament it is important to design your game play with the following four items in mind:
1. How are you going to adver tise the tournament to your players?
Look to use Engagement features to promote the tournament to players - both before it begins and while
the competition is on.
2. What are you tr ying to get your players to do?
Make sure you have a game play that is engaging, and brings your players back. Are they trying to clear
the most levels, beat the most monsters or get the highest score? Depending on your engagement goals,
you will identify the statistic that drives the tournament. Your game will send the statistic updates to
PlayFab, and you can use the leaderboards to always show your players where they stand.
3. What ends your tournament?
Is your tournament an ongoing daily or weekly event? If so, you can configure your leaderboard to reset
automatically. If not, you will need to define what ends your tournament -- and trigger the resetting of the
statistic manually.
4. How are you going to reward your players?
When the tournament ends use prize tables to grant your players awards, in game currency and bragging
rights. Remember to notify your players of all of the great rewards they have won (and bring them back
into your game)!
Tournaments and leaderboards quickstart
5/24/2022 • 2 minutes to read • Edit Online

This quickstart describes how to have a statistic that keeps track of the players high score, and how to get a
leaderboard of the top high scores. This can be utilized for a global leaderboard, or in conjunction with
resettable statistics to reset for a specific event or tournament.

Prerequisites
Your player is already logged into PlayFab.

Step 1 - Create a statistic and associated leaderboard


In the Game Manager:
Go to Leaderboards in the menu to the left.
Select NEW LEADERBOARD .
Add a Leaderboard called HighScore in the Statistic name field.
Using the drop-down menu provided, set the Reset frequency field to Manually .
Move to the Aggregation method field and select Maximum (always use the highest value) from the
drop-down menu provided.

Step 2 - Update the statistic with the high score for a player
Before we can use UpdatePlayerStatistics from the client, we must enable it in API Features .
1. Select Title settings off the Settings menu for your title.
2. Select the API Features tab.
3. Check the box for Allow client to post player statistics . NOTE: In general, this option should not be used
in a live game, as it gives the client authority over values submitted. This is only valid for cases where there is
no concern that players may cheat their statistics. If statistics need to be secure, they should only be updated
via a server authoritative operation, such as a Cloud Script or custom game server.
4. Click the SAVE button at the bottom of the screen.
C# code example - SubmitScore
In this code example we will have a SubmitScore function that would be called at the end of a game.

public void SubmitScore(int playerScore) {


PlayFabClientAPI.UpdatePlayerStatistics(new UpdatePlayerStatisticsRequest {
Statistics = new List<StatisticUpdate> {
new StatisticUpdate {
StatisticName = "HighScore",
Value = playerScore
}
}
}, result=> OnStatisticsUpdated(result), FailureCallback);
}

private void OnStatisticsUpdated(UpdatePlayerStatisticsResult updateResult) {


Debug.Log("Successfully submitted high score");
}

private void FailureCallback(PlayFabError error){


Debug.LogWarning("Something went wrong with your API call. Here's some debug information:");
Debug.LogError(error.GenerateErrorReport());
}

Step 3 - Request the leaderboard for the high score


In order to get the leaderboard of the top high scores of all players that have played the game, you will make a
call to GetLeaderboard.
C# code example - RequestLeaderboard
In this code example we will have a RequestLeaderboard function that would be called to get the leaderboard,
and will pass the results to a function of DisplayLeaderboard , which would populate the experience in your
game that shows the high scores.
//Get the players with the top 10 high scores in the game
public void RequestLeaderboard() {
PlayFabClientAPI.GetLeaderboard(new GetLeaderboardRequest {
StatisticName = "HighScore",
StartPosition = 0,
MaxResultsCount = 10
}, result=> DisplayLeaderboard(result), FailureCallback);
}

private void FailureCallback(PlayFabError error){


Debug.LogWarning("Something went wrong with your API call. Here's some debug information:");
Debug.LogError(error.GenerateErrorReport());
}
Tournaments & Leaderboards Tutorials
5/24/2022 • 2 minutes to read • Edit Online

The tutorials in this section walk you through topics involving tournaments and leaderboards.
Accessing Archived Tournament Results
Friends leaderboards
Using Prize Tables
Using resettable statistics and leaderboards
Using the Profile for Advanced Leaderboards
Accessing archived tournament results
5/24/2022 • 4 minutes to read • Edit Online

This tutorial illustrates how you can access archived leaderboard states.
Each leaderboard can be reset manually or automatically - meaning statistic values will be removed for all the
players, leading to a clear state, and the leaderboard version will be implemented.
Before that happens, however, PlayFab creates a snapshot of all the leaderboard statistic values for each player.
This allows you to access this archived version of the leaderboard.

NOTE
All titles allow you to access the most recently archived version of a leaderboard, and this gives you the current and most
previous versions. For example, if your current leaderboard version is 3 , you may access only version 3 and archived
version 2 .

Initial setup
Before using this guide, please make sure that you have some players already registered for the title. The
following screenshot shows 5 players artificially registered using the LoginWithCustomID API call.

Defining and simulating a leaderboard


In this step, we will create a leaderboard for our test purposes. Then we will simulate the leaderboard iteration
process by populating and resetting the leaderboard several times.
Open Game Manager:
1. Navigate to the Leaderboards section.
2. Select the New Leaderboard button, as shown below.
To configure the new leaderboard:
1. Set the Statistic name to TestScore .
2. Keep the Reset Frequency as Manually .
3. Leave the default Aggregation method.
4. Submit by selecting Save Leaderboard .

You will end up on the new Leaderboards page which will render blank data (see below).

Begin test section


IMPORTANT
The following section is an example of how to populate test data for the purpose of this example. Your real game will
populate this data in a more natural way.

Our next step is simulating some data for our leaderboard. The quickest way to do this is to create a CloudScript
handler, which will set random statistics for a given player. We will invoke this handler for every player over the
All Players segment.
As a result, each player will get a random statistic value, which is a good enough approximation of a real world
scenario.
Let's start with defining our CloudScript (refer to the code comments for further information).

// Should be invoked from a task that runs over certain segment


handlers.PopulateLeaderboard = (args,ctx) => {
// When handler is executed as a task over the segment
// we can extract individual player id using the next line:
let playerId = ctx.playerProfile.PlayerId;

// Use player id and update player statistics as follows:


server.UpdatePlayerStatistics({
PlayFabId : playerId,
Statistics : [
{
"StatisticName": "TestScore",
"Value": getRandomInRange(100,1000)
}
]
});
}

// Utility method to generate random number


let getRandomInRange = (min, max) => {
return Math.round(Math.random() * (max - min) + min);
}

Let's upload the CloudScript. Using Game Manager:


1. Navigate to the Automation tab.
2. Then navigate to the CloudScript sub-tab.
3. Insert the CloudScript code.
4. Select Save as Revision .
5. Finally, Deploy Revision .

Next, we need to define a task to execute our CloudScript over a specific segment:
1. Navigate to the Players tab.
2. Then, navigate to the Segments sub-tab.
By default, PlayFab generates an All Players segment for you. This segment is specifically useful when you
need all players registered in your title (which is exactly our case).
3. Select the All Players Segment .
4. Finally, select Run Task ....

NOTE
If you have no All Players segment in the list, please, refer to our Player Segmentation quickstart to create one.

To configure the task:


1. Set up the Name .
2. Make sure the type of task is set to Run actions on each Player in a Segment .
In addition, verify that All Players is selected under Segment .
3. Add a new Action .
4. Select Execute CloudScript under Type .
5. Then select the PopulateLeaderboard handler under CloudScript Function .
6. Finally, select the Save and Run button.
Make sure the execution result is Successful .

End of Test Section


Populate Test data
1. Navigate to the Leaderboards tab again.
2. Select our Leaderboard .
1. You will see that your Leaderboard was populated with random values.
2. Reset the Leaderboard .

This will create a snapshot of all the data we currently have, and then it will nullify statistic values on every
player and increment the version.
Once your leaderboard is reset, run the CloudScript task again.
Repeat this 2-3 times, then reset and repopulate.
You will end up with several Leaderboard versions (1) :
Current version data will be displayed in the table to the left (3) .
Archived data will be available for previous versions (2) .
Only the latest version will be available. This applies to all titles.
Accessing archived data using Game Manager
You can access archived results directly from the Leaderboard page:
1. Navigate to the Leaderboards tab.
2. Select the Leaderboard you need.

1. If your Leaderboard contains archived revisions, you will be able to download JSON data using the
download link shown in the screenshot below.
Accessing archived data using API
The following code allows you to pull the latest (current) version of the leaderboard.

PlayFabClientAPI.GetLeaderboard(new GetLeaderboardRequest()
{
StatisticName = "TestScore",
}, result =>
{
Debug.Log("Leaderboard version: "+result.Version);
foreach (var entry in result.Leaderboard)
{
Debug.Log(entry.PlayFabId+" "+entry.StatValue);
}
}, FailureCallback);

The result will look like the example provided below.

Alternatively, you may specify a version of the leaderboard you want to load.
PlayFabClientAPI.GetLeaderboard(new GetLeaderboardRequest()
{
StatisticName = "TestScore",
Version = 1
}, result =>
{
Debug.Log("Leaderboard version: "+result.Version);

foreach (var entry in result.Leaderboard)


{
Debug.Log(entry.PlayFabId+" "+entry.StatValue);
}
}, FailureCallback);

The result will look like the example provided below.

All titles allow you to access the latest archived version of the leaderboard. Trying to pull an older version will
result in an error (see below).

The same rules apply for all the Leaderboard requests.


GetLeaderboard
GetLeaderboardAroundPlayer
GetFriendLeaderboardAroundPlayer
GetFriendLeaderboard
Please refer to documentation for the GetLeaderboardResult object, to learn about useful properties you may
get with the leaderboard data.
Using prize tables
5/24/2022 • 6 minutes to read • Edit Online

This tutorial walks you through how to create a prize table that triggers a set of actions on a group of players
within a range of ranks, in a Resettable Leaderboard.
In particular, this is a way to trigger emails, send push notifications, grant Inventory Items and Virtual Currency,
or execute a CloudScript function at the reset of a leaderboard.
In this example, we show you how to create prize table end tournament prizes, which grants virtual currency to
5 players based on their rank in a leaderboard after a reset is performed.

Requirements
IMPORTANT
This is an advanced tutorial. Please make sure that all requirements shown below have been met, or you will not be able
to complete this tutorial.

Basic knowledge of how to create a player will be necessary, as there will need to be players in a leaderboard
before it can perform any actions on those players.
It is also worthwhile to read the Game Manager quickstart if you are unfamiliar with the Game Manager, as it
is the place where prize tables are created.
In order to use Prize Tables, you must have general knowledge of how resettable leaderboards work. Please
read about leaderboards in our tutorial Using Resettable Statistics and Leaderboards.
Additionally, virtual currencies must be set up. Please read our tutorial about Currencies and set up two
currencies with the following parameters:
Currency code : GO
Display name : Gold
Initial deposit : 200
Currency code : SI
Display name : Silver
Initial deposit : 1000

Step 1 - Create a leaderboard


In the Game Manager:
Go to Leaderboards in the menu to the left.
Select New Leaderboard .
Add a Leaderboard called tournamentScore_manual in the Statistic name field.
Using the drop-down menu provided, set the Reset frequency field to Manually .
Move to the Aggregation method field and select Maximum (always use the highest value) from the
drop-down menu provided.
Step 2 - Create a prize table for the leaderboard
Now that a leaderboard has been created, a prize table can be associated with it. Go to:
Leaderboards in the menu to the left.
Select the Prize Tables tab.
Select the NEW PRIZE TABLE button to be taken to the New Prize Table view.

In the New Prize Table view:


Move to the INFO area, and enter the Name for the New Prize Table , entitled End Tournament Prizes .
Choose tournamentScore_manual from the Leaderboard drop-down menu.
In order for this Prize Table to perform some action, ranks will need to be set. To do this:
Select + ADD RANK under the TABLE CONTENTS section.
A Rank form will appear.

In the Rank form:


Verify that the Rank from field has a value of 1 .
Verify that the To (inclusive) field has a value of 2 .
In the Type drop-down menu, choose Grant vir tual currency .
In the vir tual currency code drop-down menu, choose GO (Gold) with an amount of 10 .
Now, we'll add a second rank range:
Select +ADD RANK under the TABLE CONTENTS section (there is also a second one at the bottom, that
also works).
In the Rank form that appears, make sure that the Rank from field has a value of 3 and the To (inclusive)
field has a value of 5 .
In the Vir tual currency code drop-down, choose SI (Silver ) with an amount of 10 .
Step 3 - Populate the leaderboard with a player
A leaderboard and prize table associated with it has now been created. The next step is to populate the
leaderboard with players.
To create players, we will use LoginWithCustomID. Then, we will use the players to populate the leaderboard
with UpdatePlayerStatistics.
Before we can use UpdatePlayerStatistics, we must enable it in API Features.
Select Settings in the menu on your left.
Select the API Features tab.
Check the box for Allow client to post player statistics .
Then select the SAVE API FEATURES button at the bottom of the screen.
C# code example
The following C# code example creates 5 players, and logs them in using LoginWithCustomID.
It then populates the leaderboard you created earlier ( tournamentScore_manual ) with the 5 players with values of:
105 , 104 , 103 , 102 , and 101 using UpdatePlayerStatistics.

// Note: This is a recursive function. Invoke it initially with no parameter


public void CreatePlayerAndPopulateLeaderboard(int playerIndex = 5) {
if (playerIndex <= 0) return;
const string leaderboardName = "tournamentScore_manual";
PlayFabClientAPI.LoginWithCustomID(new LoginWithCustomIDRequest {
CustomId = playerIndex.ToString(),
CreateAccount = true
}, result => OnLoggedIn(result,playerIndex,leaderboardName), FailureCallback);
}

private void OnLoggedIn(LoginResult loginResult, int playerIndex, string leaderboardName) {


Debug.Log("Player has successfully logged in with " + loginResult.PlayFabId);
PlayFabClientAPI.UpdatePlayerStatistics(new UpdatePlayerStatisticsRequest {
Statistics = new List<StatisticUpdate> {
new StatisticUpdate {
StatisticName = leaderboardName,
Value = playerIndex + 100
}
}
}, result=> OnStatisticsUpdated(result,playerIndex), FailureCallback);
}

private void OnStatisticsUpdated(UpdatePlayerStatisticsResult updateResult, int playerIndex) {


Debug.Log("Successfully updated player statistic");
// Recursively invoke for next player
CreatePlayerAndPopulateLeaderboard(playerIndex - 1);
}

private void FailureCallback(PlayFabError error){


Debug.LogWarning("Something went wrong with your API call. Here's some debug information:");
Debug.LogError(error.GenerateErrorReport());
}

Check results of the C# code example


To check that there are 5 players populated in the leaderboard with the correct values:
Select Leaderboards from the menu on the left.
On the Leaderboards tab, go back to the Leaderboard list view.
Select tournamentScore_manual , and there should be 5 Players with the values of 105 , 104 , 103 , 102 ,
and 101 .

Step 4 - Check player's initial currencies


Before checking anything:
Return to Players in the menu to the left from step 2.
Go to the Players tab, and find a player that was put into the tournamentScore_manual Leaderboard in
step 3.
Select the Player ID , and the Vir tual Currency tab for that player.
Record the values of the GO (Gold ) and SI (Silver ) Currencies for that player.
Before checking anything, go back to the test Players from step 2.
Go to Players and find one that was put into tournamentScore_manual Leaderboard in step 3.
Select the Player ID and the Vir tual Currency tab for that player.
Record the values of the GO (Gold ) and SI (Silver ) currencies for that player.
Now do this for the remaining 4 of the 5 players that were put in the tournamentScore_manual
Leaderboard in step 3.
Make sure that you record the values of their GO (Gold ) and SI (Silver ) currencies (these will be important
for confirmation that the Prize Table worked after resetting).
Step 5 - Reset the leaderboard to grant rewards
Now go to Leaderboards .
Go back to the Leaderboards list view.
Select tournamentScore_manual .
Make a note of the positions of the Players on the Leaderboard (these are zero indexed, so position 0
will be first place).
Select the RESET NOW button.
Select RESET button to confirm the reset of the Leaderboard
This will clear the Players list.

Select the RESET NOW button at the top of the screen.


When prompted to Reset this Leaderboard now? , select the RESET button to confirm the reset.
This will clear the Players list.
Step 6 - Test that the prize table works
To see if the Prize Table worked, the players in the leaderboard can be checked to see if they were granted the
correct amounts of currency. This can be quickly seen in a player's PlayStream Debugger.
To see this in the PlayStream Debugger:
Select Players from the menu on your left.
The PlayStream tab will show a Player ranking on a Leaderboard event, followed by a Vir tual Currency
update.
Now, let's manually check if the players received the correct currencies:
Select Players from the menu on your left.
On the Players tab, move to the Vir tual Currency area of the screen.
Verify that the currency was granted correctly.
This should be one more than the amount recorded earlier.
Notice that Players in leaderboard positions 0 or 1 gained 10 gold with no silver being awarded.
Meanwhile, Players in positions 2 , 3 , and 4 were granted 10 silver and no gold.
This matches the actions set up for the prize table.
Another way of checking that the Vir tual Currency was granted correctly is:
Go into Players .
Look at the Event Histor y .
This will show a player_vir tual_currency_balance_changed event with specific details on amounts that
changed for the Vir tual Currency granted.
Using resettable statistics and leaderboards
5/24/2022 • 13 minutes to read • Edit Online

This tutorial provides a complete walkthrough of how to configure and manage statistics with versioning -
which enables resetting of statistics - and by extension, leaderboards.
We'll focus on how to use the Admin API methods, with additional info on how to use the client and Server API
methods to query the data - both for the current version as well as old ones.
Our goal is to provide you with a technical review of how re-settable statistics work in PlayFab, and all the ways
they can be used in your games.

Statistics and leaderboards


First, it’s important to note that all statistics defined for a player in a game in PlayFab are part of a leaderboard.
So defining your statistics defines your leaderboard as well.
Statistics may not necessarily be visible to players, but they are there. You can use them to get lists of players by
a score you define - whether to find the top of all scores, the bottom, those centered around the current player -
or those on a user’s friend list.
Many statistics in games are intended to be lifetime values - meaning that players continually update their
scores, with old ones remaining until each player beats his own personal best. However, for some player
experiences, it’s important to be able to “wipe” the leaderboard from time to time.
This can be used to encourage a user to try to be the top ranked player for a given period, or to simply remove
any players from the rankings who haven’t been active in a while.
As this tutorial will discuss, statistics in PlayFab can be configured to reset on a pre-determined interval.
This is useful not just for the scenarios described above - it can also be used for titles that need to have a distinct
leaderboard of recent scores, which can be used for things like game challenges, where you want to let a player
issue an invitation to someone of a similar skill level.
Setting a reset period means that the players returned in a call to GetLeaderboardAroundPlayer, for example,
are those that have recently played the game, and who have scores similar to the local player.
It’s also possible to reset a statistic as a manual operation. This is a handy system for clearing out any data you
have from your pre-launch tests or alpha/beta play.
It’s also useful for the worst case scenario, where a bug was introduced to the game code resulting in out-of-
control scores. In each case, you need to have the ability to wipe the leaderboard clean, so that players feel like
they have a fair chance to get on it.

NOTE
Resetting statistics does not delete those values, as you will see below. On reset, statistics in PlayFab are versioned,
making the new version authoritative, while keeping previous versions for later analysis (and so that you can reward
players based on their old scores).

Configuring resettable statistics


The reset periods for statistics are configured using the Admin API set or the Game Manager. They can then be
updated and queried via the Game Manager, Server API, and Client API (though posting statistics from the client
does require that the allow client to post statistics option be set in the game's Settings ->API Features tab
in the Game Manager).
We’ll describe the API method for this, though the parameters defined here are the same as those used in the
Game Manager itself.
To set up the statistics, you can use the Admin CreatePlayerStatisticDefinition method, and the
UpdatePlayerStatisticDefinition method to make changes later.

In both cases, there are only two parameters:


StatisticName - The string identifier for the player statistic.
VersionChangeInterval - The period defining when the statistics should be automatically reset.

The VersionChangeInterval is the key to this feature, and it can be defined as hourly, daily, weekly, or monthly. It
can also be set to never, if you decide later that you no longer want the statistic to reset on a regular basis.
In the example that follows, the call to the CreatePlayerStatisticDefinition method sets up the statistic
Headshots with a daily reset, meaning that the leaderboard for this statistic in the game will reset every day at
00:00 UTC.

public void CreatePlayerStatisticDefinition() {


PlayFabAdminAPI.CreatePlayerStatisticDefinition(
new CreatePlayerStatisticDefinitionRequest() {
StatisticName = "Headshots",
VersionChangeInterval = StatisticResetIntervalOption.Day
},
result => Debug.Log("Complete"),
error => Debug.Log(error.GenerateErrorReport())
);
}

The following shows the response for the preceding API call.

{
"code": 200,
"status": "OK",
"data":
{
"Statistic":
{
"StatisticName": "Headshots",
"CurrentVersion": 0,
"VersionChangeInterval": "Day"
}
}
}

The coding shown below is an alternative example.


public void UpdatePlayerStatisticDefinition() {
PlayFabAdminAPI.UpdatePlayerStatisticDefinition(
new UpdatePlayerStatisticDefinitionRequest() {
StatisticName = "Headshots",
VersionChangeInterval = StatisticResetIntervalOption.Week
},
result => Debug.Log("Complete"),
error => Debug.Log(error.GenerateErrorReport())
);
}

The call demonstrates setting the reset period for the statistic to weekly, with the following response.

{
"code": 200,
"status": "OK",
"data":
{
"Statistic":
{
"StatisticName": "Headshots",
"CurrentVersion": 0,
"VersionChangeInterval": "Week"
}
}
}

In each case, the result is the PlayerStatisticDefinition , containing:


The string ID of the statistic ( StatisticName ).
The number of times the statistic has been reset ( CurrentVersion ).
The defined period for when the statistic will reset ( VersionChangeInterval ).

The reset periods take effect as soon as they are defined, so in this case, the second call means that the reset is
now defined as 00:00 UTC, Monday morning (midnight on Sunday night/Monday morning, using the UTC
timezone), regardless of what it was before the call.
The remaining reset intervals are also defined using UTC, with Month making the reset occur at 00:00 UTC on
the first day of each month.
For the completed list, the reset periods are:
Never : Stop versioning the statistic on a time-based basis.
Hour : Version the statistic at the top of every Hour (XX:00 UTC).
Day : Version the statistic at midnight (00:00 UTC) every Day .
Week : Version the statistic at midnight (00:00 UTC) every Monday.
Month : Version the statistic at midnight (00:00 UTC) on the first day of every Month.

Preexisting Statistics
All statistics defined in the game can be queried for their definition, regardless of whether they were set up as
resetting statistics or not.
This is important to note, since statistics can be created using the UpdatePlayerStatistics call. Any statistics not
created with a reset period ( VersionChangeInterval ) will not have one to start, and so a query for the statistic
configuration would return with this parameter set to Never .
Using the example above, if the title also had a statistics named FlagsCaptured created using
UpdatePlayerStatistics (or created in the Game Manager directly on a player), and a couple of weeks had passed,
it would appear as shown in the call shown below.

public void GetPlayerStatisticDefinitions() {


PlayFabAdminAPI.GetPlayerStatisticDefinitions(
new GetPlayerStatisticDefinitionsRequest(),
result => Debug.Log("Complete"),
error => Debug.Log(error.GenerateErrorReport())
);
}

Would result in the following.

{
"code": 200,
"status": "OK",
"data":
{
"Statistics": [
{
"StatisticName": "Headshots",
"CurrentVersion": 2,
"VersionChangeInterval": "Week"
},
{
"StatisticName": "FlagsCaptured",
"CurrentVersion": 0,
"VersionChangeInterval": “Never”
}]
}
}

In this case, the statistics named Headshots has a reset interval defined, and CurrentVersion indicates that the
statistics has been reset twice.
Meanwhile, FlagsCaptured does not have a VersionChangeInterval , which is also why the CurrentVersion is 0
(since it has never been versioned).
Statistics created via UpdatePlayerStatistics (or the PlayFab Game Manager), can still be defined to have a reset
period using UpdatePlayerStatisticDefinition , as described above.
Once this has been done, they will reset on that interval exactly as if they were originally defined using
CreatePlayerStatisticDefinition .

Manually resetting a statistic


For the situation where a game bug allowed for cheating on a statistic, or where you simply need to reset to
remove scores from pre-release gameplay, the statistic can be forced to reset in the Game Manager, or via a call
to IncrementPlayerStatisticVersion .
This immediately resets the current statistics that you specify, clearing the leaderboard for the game, and
providing a blank slate for new values to be reported.
For our example, this call might look like the one shown below.
public void IncrementPlayerStatisticVersion() {
PlayFabAdminAPI.IncrementPlayerStatisticVersion(
new IncrementPlayerStatisticVersionRequest() {
StatisticName = "Headshots"
},
result => Debug.Log("Complete"),
error => Debug.Log(error.GenerateErrorReport())
);
}

This increments the Headshots statistic once more, returning information on the version which has just been
made active.

{
"code": 200,
"status": "OK",
"data":
{
"StatisticVersion":
{
"StatisticName": "Headshots",
"Version": 3,
"ActivationTime": "2016-02-03T08:02:29.864Z",
"ArchivalStatus": "NotScheduled"
}
}
}

In this case, the PlayerStatisticVersion information is returned, containing the ID of the statistic (
StatisticName ), as well as its version number, the time when it became the authoritative version (
ActivationTime ), and the ArchivalStatus (which will always be NotScheduled for the current version).

However, for a statistic which also has a VersionChangeInterval , manually resetting will not change the next
scheduled reset time. If a statistic is scheduled to reset on a daily basis - and it is manually reset at 11:30 PM UTC
- it will still reset again at midnight UTC.
When the reset occurs
As stated, when the reset interval occurs, the statistic will be versioned, so that a new version is immediately
available, while the old version of that statistic is archived for later retrieval.
Once the reset interval occurs (or a manual reset is performed), and the statistic is versioned, writes to the old
version will be accepted for up to ten minutes. Beyond that point, the statistic is locked, preventing future
updates.
Once expired, statistics start into the archive process, so that they can be retrieved by the title later.
The stages of the archival process for a statistic are:
NotScheduled - Archiving of the statistic has not started (normally only for the currently active statistic
version).
Scheduled - The archive process has been scheduled, but is not underway yet.
InProgress - The statistic is being backed up to the archive.
Failed - An unexpected failure occurred (in this case, contact our Support Forums).
Complete - This version of the statistic has been archived.
All of the past and current versions of a statistic can be queried using GetPlayerStatisticVersions . This returns
the information for each version, as shown in the previous manual reset example.
In other words, this call should appear like the one presented below.

public void GetPlayerStatisticVersions() {


PlayFabAdminAPI.GetPlayerStatisticVersions(
new GetPlayerStatisticVersionsRequest() {
StatisticName = "Headshots"
},
result => Debug.Log("Complete"),
error => Debug.Log(error.GenerateErrorReport())
);
}

This could result in the following information being returned for our example title.

{
"code": 200,
"status": "OK",
"data":
{
"StatisticVersions": [
{
"StatisticName": "Headshots",
"Version": 0,
"ActivationTime": "2015-01-20T05:47:27.17Z",
"DeactivationTime": "2016-01-25T00:00:00.000Z",
"ArchivalStatus": "Complete",
"ArchiveDownloadUrl": {{URL}}
},
{
"StatisticName": "Headshots",
"Version": 1,
"ActivationTime": "2016-01-25T00:00:00.000Z",
"DeactivationTime": "2016-02-01T00:00:00.000Z",
"ArchivalStatus": "Complete",
"ArchiveDownloadUrl": {{URL}}
},
{
"StatisticName": "Headshots",
"Version": 2,
"ActivationTime": "2016-02-01T00:00:00.000Z",
"DeactivationTime": "2016-02-03T08:02:29.864Z",
"ArchivalStatus": "InProgress"
},
{
"StatisticName": "Headshots",
"Version": 3,
"ActivationTime": "2016-02-03T08:02:29.864Z",
"ArchivalStatus": "NotScheduled"
}]
}
}

In addition to the values returned from IncrementPlayerStatisticVersion , the response also includes the
timestamps for when each version was expired ( DeactivationTime ) for versions prior to the current active one,
and a URL for downloading the CSV containing the complete record of the old leaderboard, once the archive
process has completed ( ArchiveDownloadUrl ).
Reading and writing to statistic versions
Finally, from the server and client API side of the story, the calls are very similar to what you know from original
PlayFab user and character statistics calls.
The difference is that now, the version is part of either the request or the response.
When retrieving statistics, the value for the current statistic version - as well as the version number itself - is
returned.
The following examples show making the call for the Headshots statistic, as well as the returned data.
Server Request

public void GetPlayerStatistics() {


PlayFabServerAPI.GetPlayerStatistics(
new GetPlayerStatisticsRequest() {
PlayFabId= "_PlayFabId_",
StatisticNames = new List<string>() { "Headshots" }
},
result => Debug.Log("Complete"),
error => Debug.Log(error.GenerateErrorReport())
);
}

Server response

{
"code": 200,
"status": "OK",
"data":
{
"PlayFabId": {{PlayFabId}},
"Statistics": [
{
"StatisticName": "Headshots",
"Value": 10,
"Version": "3"
}]
}
}

Client request

public void GetPlayerStatistics() {


PlayFabClientAPI.GetPlayerStatistics(
new GetPlayerStatisticsRequest() {
StatisticNames = new List<string>() { "Headshots" }
},
result => Debug.Log("Complete"),
error => Debug.Log(error.GenerateErrorReport())
);
}

Client response

{
"code": 200,
"status": "OK",
"data": {
"Statistics": [
{
"StatisticName": "Headshots",
"Value": 10,
"Version": "3"
}]
}
}

Meanwhile, the Update call takes an optional version, to allow the title to control which version is being
updated, for cases where the version may have incremented during game play.

NOTE
In this example, if the title were to write to the previous version while it is still possible, it would be writing to Version 2, as
shown below.

Server request

public void UpdatePlayerStatistics() {


PlayFabServerAPI.UpdatePlayerStatistics(
new UpdatePlayerStatisticsRequest() {
PlayFabId= "_PlayFabId_",
Statistics = new List<StatisticUpdate>() {
new StatisticUpdate() {
StatisticName = "Headshots",
Version = 2,
Value = 10
}
}
},
result => Debug.Log("Complete"),
error => Debug.Log(error.GenerateErrorReport())
);
}

Server response

{
"code": 200,
"status": "OK",
"data": {}
}

Client request

public void UpdatePlayerStatistics() {


PlayFabClientAPI.UpdatePlayerStatistics(
new UpdatePlayerStatisticsRequest() {
Statistics = new List<StatisticUpdate>() {
new StatisticUpdate() {
StatisticName = "Headshots",
Version = 2,
Value = 10
}
}
},
result => Debug.Log("Complete"),
error => Debug.Log(error.GenerateErrorReport())
);
}

Client response

{
"code": 200,
"status": "OK",
"data": {}
}

But remember - while the expired version can be written to for up to 10 minutes, any attempt to write to that
version beyond that time will fail, with a response like the one shown below.

{
"code": 400,
"status": "BadRequest",
"error": "StatisticVersionClosedForWrites",
"errorCode": 1197,
"errorMessage": "The statistic version is not current and is no longer accepting updates"
}

Resources
For completeness, this section provides a list of all the enums, classes, and API methods described above, with
brief descriptions.
Base enums
Inter val - period at which rate the statistic (leaderboard) will be reset:
Never
Hour
Day
Week
Month
StatisticVersionArchivalStatus - the status of the process of saving the player statistic values of a
version to a downloadable archive:
NotScheduled
Scheduled
InProgress
Failed
Complete
Base classes and their members
PlayerStatisticDefinition
StatisticName (string) - The unique name of the statistic.
CurrentVersion (string) - The current active version of the statistic, incremented each time the
statistic resets.
VersionChangeInter val (Interval) - The interval at which the values of the statistic for all players are
reset.
PlayerStatisticVersion
StatisticName (string) - The name of the statistic when the version became active.
Version (string) - The version of the statistic (a hexadecimal number encoded as a string).
ScheduledVersionChangeInter valTime (DateTime) - The time at which the statistic version was
scheduled to become active, based on the configured ResetInter val .
CreatedTime (DateTime) - The time when the statistic version became active.
ArchivalStatus (StatisticVersionArchivalStatus ) - The status of the process of saving player
statistic values of this version to a downloadable archive, if configured.
ResetInter val (Interval) - The reset interval that triggered the version to become active, if configured.
StatisticValue
StatisticName (string) - The unique name of the statistic.
Value (Int32) - The statistic value for the player.
Version (string) - For an existing statistic value for a player, the version of the statistic when it was
loaded.
StatisticUpdate
StatisticName (string) - The unique name of the statistic.
Version (string) - For updates to a statistic value for a player, the version of the statistic to be updated
Value (Int32) - The statistic value for the player.
Admin API methods
CreatePlayerStatisticDefinition
CreatePlayerStatisticDefinitionRequest
Name (string) - min length 1, max length 128 - The unique name of the statistic.
(VersionChangeInter val ) (Interval) - The interval at which the values of the statistic for all
players are reset (resets begin at the next interval boundary).
CreatePlayerStatisticDefinitionResult
Statistic (PlayerStatisticDefinition ) - The created statistic's definition.
UpdatePlayerStatisticDefinition
UpdatePlayerStatisticDefinitionRequest
StatisticName (string) - The unique name of the statistic.
VersionChangeInter val (Interval) - The interval at which the values of the statistic for all
players are reset (resets begin at the next interval boundary).
UpdatePlayerStatisticDefinitionResult
Statistic (PlayerStatisticDefinition ) - The created statistic's definition.
GetPlayerStatisticDefinitions
GetPlayerStatisticDefinitionsRequest (no parameters).
GetPlayerStatisticDefinitionsResult
Statistics (PlayerStatisticDefinition[] ) - The array of definitions for the resetting.
GetPlayerStatisticVersions
GetPlayerStatisticVersionsRequest
StatisticName (string) - The unique name of the statistic.
GetPlayerStatisticVersionsResult
StatisticVersions (PlayerStatisticVersion[] ) - The version change history of the statistic (all
the versions).
IncrementPlayerStatisticVersion
IncrementPlayerStatisticVersionRequest
StatisticName (string) - The unique name of the statistic.
IncrementPlayerStatisticVersionResult
StatisticVersion (PlayerStatisticVersion ) - The statistic version which was expired as a
result of this operation (and its archival status).
Client API methods
GetPlayerStatistics
GetPlayerStatisticsRequest
StatisticNames (string[]) - Array of statistic to be returned, by their unique names.
GetPlayerStatisticsResult
Statistics (StatisticValue[] ) - Array of StatisticValue data for all the statistic requested.
UpdatePlayerStatistics
UpdatePlayerStatisticsRequest
Statistics (StatisticUpdate[] ) - The statistic to be updated, with the provided values.
UpdatePlayerStatisticsResult (no parameters).
Server API methods
GetPlayerStatistics
GetPlayerStatisticsRequest
PlayFabId (string) - The PlayFab ID of the player whose statistics are being updated.
StatisticNames (string[]) - Array of statistics to be returned, by their unique names.
GetPlayerStatisticsResult
Statistics (StatisticValue[] ) - Array of StatisticValue data for all the statistic requested.
UpdatePlayerStatistics
UpdatePlayerStatisticsRequest
PlayFabId (string) - The PlayFab ID of the player whose statistics are being updated.
Statistics (StatisticUpdate[] ) - The statistic to be updated, with the provided values.
UpdatePlayerStatisticsResult (no parameters).
Using the profile for advanced leaderboards
5/24/2022 • 2 minutes to read • Edit Online

With PlayFab, you usually construct leaderboards using the following API methods:
GetFriendLeaderboard
GetFriendLeaderboardAroundPlayer
GetLeaderboard
GetLeaderboardAroundPlayer
The result is a list of PlayerLeaderboardEntr y objects that contain only basic information about the player,
and their relation to the current leaderboard.
However, PlayFab also allows you to use PlayerProfileViewConstraints , to gain additional information about
each player.

NOTE
This example assumes you already have some leaderboard data to play with. Please refer to our Accessing Archived
Tournament Results tutorial, for a method to generate some test data.

Configuring player profile view constraints


By default, the Client API may only fetch the display name from another player profile. In this example, we will
allow all players to access additional information about other players in the leaderboard.
Navigate to your title Game Manager:
1. Select the Settings icon in the menu to the left.
2. Select Title settings
3. Then select the Client Profile Options tab.
4. Verify that the DisplayName is selected.
5. Make sure that the Avatar URL is selected.
6. Submit your changes by selecting the Save Client Profile Options button.
Testing
The previous step allows client code to use DisplayName and AvatarUrl profile constraints.
The following sample shows how to fetch and print a leaderboard using any mentioned Profile data. Please refer
to the code comments for further information.
private static async Task DoReadLeaderboard()
{
// Get Leaderboard Request
var result = await PlayFabClientAPI.GetLeaderboardAsync(new GetLeaderboardRequest()
{
// Specify your statistic name here
StatisticName = "TestScore",
// Override Player Profile View Constraints and fetch player DisplayName and AvatarUrl
ProfileConstraints = new PlayerProfileViewConstraints()
{
ShowDisplayName = true,
ShowAvatarUrl = true
}
});

// Start printing the leaderboard


Console.WriteLine("=== LEADERBOARD ===");

if (result.Error != null)
{
// Handle error if any
Console.WriteLine(result.Error.GenerateErrorReport());
}
else
{
// Traverse the leaderboard list
foreach (var entry in result.Result.Leaderboard)
{
// Print regular leaderboard entry information
Console.WriteLine($"{entry.Position + 1} {entry.PlayFabId} {entry.StatValue}");

// Additionally print display name and avatar url that comes from player profile
Console.WriteLine($" {entry.Profile.DisplayName} | {entry.Profile.AvatarUrl}");
}
}
}

NOTE
The individual Profile fields are only available if the client explicitly asks for them using Profile Constraints. Also be aware
that if certain profile constraint are not allowed in the Game Manager - and your client requests them - the API call will
fail with a corresponding error. The result will look similar to the example provided below.
Using this technique, you can fetch a handful of Profile information, including other statistic values.
Friends leaderboards
5/24/2022 • 2 minutes to read • Edit Online

Friends-specific APIs mirror the standard GetLeaderboard and GetLeaderboardAroundPlayer API calls, but
restrict the player pool to the player's friends list.

NOTE
The GetFriendLeaderboardAroundPlayer API does not base the center of the leaderboard around the currently logged in
player - it can be any PlayFab ID supplied with the request. You can use this to allow players to look up any friend's
location on the leaderboard, regardless of their distance from each other.
Trading
5/24/2022 • 2 minutes to read • Edit Online

The PlayFab client API allows players to trade items with one another. These API methods are enabled by default,
so for the security of your title you may need to use our policy API to disable them.

NOTE
Inventory-trading functionality is in a preview phase. The methods are functional, but lack some useful elements that
would make it a complete feature. Currently you can only trade virtual items. You cannot request or trade virtual currency,
and PlayFab does not provide a list of trades that are available to you from other players. Trade methods are only
available in the client API, and not available from the server API.

Key concepts
Catalog - Catalogs offer an easy way to manage your game's virtual items. They are listings of every item that
is available in your game.
Catalog Items – PlayFab Items can represent just about any type of virtual goods that you might use - from
durables, to bundles to locked containers.
Inventor y - All accounts (player accounts and character accounts) have an inventory. The inventory contains all
owned item instances, as well as item history.
Vir tual Currency - PlayFab offers up to 10 virtual currencies per title. Currencies can be used to purchase
items from a catalog or store, can represent soft currency converted from in-app purchases, or they can be used
as a mechanic to drive gameplay.

Prerequisites
Trading requires familiarity with both catalog and inventory items. Players must own inventory items they wish
to trade.

APIs
Trading flow is handled by a handful of APIs:
OpenTrade
Opens a new outstanding trade. This can between two specific players (PlayfabIDs) or with one player opening a
trade open to anyone. Understand that any single given item instance may only be in one open trade at a time.
GetTradeStatus
Allows a client to evaluate a given trade by getting its current status.
AcceptTrade
Accepts an open trade. If the call is successful, the offered and accepted items will be swapped between the two
players' inventories.
CancelTrade
Cancels an open trade. Note that only the player who created the trade can cancel it via this API call, to prevent
grief.
GetPlayerTrades
GetPlayerTrades will return all trades a player has either opened or accepted, optionally filtered by trade
status.
Trading quickstart
5/24/2022 • 2 minutes to read • Edit Online

NOTE
This quickstart assumes you are already familiar with both catalogs and inventory items. The example player must already
own the inventory items they wish to trade away.

The first step is to call the OpenTrade API, to make a trade available to another player. You will need a playfabId
to identify the gift recipient, and the ItemInstanceID for the player who currently has the item in their Inventory.
secondPlayerId : This is the unique string that identifies the gift recipient ( PlayFabId ).
myItemInstanceId : This is the unique string that identifies an item instance owned by the current player (
InstanceID ).

void GiveItemTo(string secondPlayerId, string myItemInstanceId) {


PlayFabClientAPI.OpenTrade(new OpenTradeRequest {
AllowedPlayerIds = new List<string> { secondPlayerId }, // PlayFab ID for the friend who will
receive your gift
OfferedInventoryInstanceIds = new List<string> { myItemInstanceId } // The item instanceId fetched
from GetUserInventory()
}, LogSuccess, LogFailure);
}

NOTE
All trades are public information. Any player may look at the open trades of another player, as well as another player's
trade history (If they know the playFabId of that player).

In this snip the LogSuccesscallback must also evaluate result.Trade.TradeId , and transfer both
firstPlayFabId and the tradeId to the second player. If not saved, it will not be possible for the second player
to evaluate or accept the trade.

NOTE
In the current preview you need to ensure that your trades are thread-safe from concurrent actions. Thread-safe options
include custom game servers and Webhook calls via CloudScript to an external database/system. Thread-Unsafe options
can be built with CloudScript which directly modifies a Player Data Key. The latter option has concurrency issues where
simultaneous trade-list-updates may not process correctly.

Once the first player has created the trade, and transferred their playFabId and the tradeId to the second
player, the second player can examine the trade requirements (verifying it is a gift) by making a GetTradeStatus
request.
NOTE
The most relevant TradeStatus values are Open , Filled , and Canceled . All other states are intermediate states. Trades
may stay in those intermediate states for a noticeable period of time between calls. A recently-modified trade may not be
available immediately.

void ExamineTrade(string firstPlayFabId, string tradeId) {


PlayFabClientAPI.GetTradeStatus(new GetTradeStatusRequest {
OfferingPlayerId = firstPlayFabId,
TradeId = tradeId
}, LogSuccess, LogFailure);
}

If the requirements of that trade are acceptable, the gift can be accepted using AcceptTrade
C# snip
void AcceptGiftFrom(string firstPlayFabId, string tradeId) {
PlayFabClientAPI.AcceptTrade(new AcceptTradeRequest {
OfferingPlayerId = firstPlayFabId,
TradeId = tradeId
}, LogSuccess, LogFailure);
}

Once complete, the AcceptGiftFrom function above will transfer the gifted items from the first player's inventory
to the second.
Introduction to Leaderboards v2
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
This feature is currently in Private Preview .
This documentation is provided to give you an early look at an upcoming feature and to allow you to provide feedback
while it is still in development.
Access to this feature is restricted to select titles that PlayFab actively reaches out to.

Overview
Leaderboards are such a significant part of game development that we are constantly iterating on customer
feedback. To cater to new customer needs, we are currently developing a second version of Leaderboards APIs
that would allow many more functionalities that our current Leaderboards APIs don't. Aligned with the new
PlayFab entity model, the new APIs sit on top of entity statistics and is backed by Azure.
Classic Leaderboards Vs. Leaderboards v2
You can now rank other entity types, in addition to Players that v1 supported.
V2 added the feature of child leaderboards, which allows categorization of leaderboards within the title.
You can now dynamically add leaderboards on the go
You can now delete leaderboards
V2 is based on PlayFab's new entity model
Updated UX design to support the new features
Leaderboards Vs. Statistics
Leaderboards are a type, or a subset of Statistics. In other words, it is possible for a Statistic to not be a
Leaderboard, but all Leaderboards have to be Statistics. When a Statistic is not a Leaderboard, it just contains a
list of unranked entries of entities (e.g. players) and values (e.g. scores).
Leaderboards v2 QuickStart
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
This feature is currently in Private Preview .
This documentation is provided to give you an early look at an upcoming feature and to allow you to provide feedback
while it is still in development.
Access to this feature is restricted to select titles that PlayFab actively reaches out to.

Creating a new leaderboard


In the Game Manager:

Go to Leaderboards in the menu to the left.


Select NEW LEADERBOARD .
Configure your new leaderboard the way you want.
"Statisitc name" is the name of your new leaderboard. Note that you won't be able to edit the name
once the leaderboard is created. -** "Reset frequency" is how often you want your leaderboard
to automatically reset. It is currently greyed out because our v2 doesn't suppor t
automatic reset yet. - "Agrregation method"** applies to the values in your new leaderboard.
Toggle "Classic statistics" to make it a v1, or "Classic" leaderboard.
If enabled, "Sort direction" and "Child leaderboards" fields will disappear as they are not
features supported in v1.
"Sor t direction" allows you to rank your leaderboard in either acsending or descending order.
"Child leaderboards" allows you to choose between Dynamic and Fixed, with the differences
mentioned under Child Leaderboards secion above. Note that you won't be able to change this
setting once you create your leaderboard.
Click SAVE .
Making API calls
Alternatively, you can also create a new leaderboard by calling the CreateStatisticDefinition API.

private static void createNewLeaderboard() {


// First, create the request
PlayFabLeaderboardsModels.CreateStatisticDefinitionRequest createStatisticDefinitionRequest = new
PlayFabLeaderboardsModels.CreateStatisticDefinitionRequest();

// Configure your request


createStatisticDefinitionRequest.Name = "New Leaderboard";

// Create a new leaderboard with your configured request


PlayFabLeaderboardsAPI.CreateStatisticDefinition(createStatisticDefinitionRequest);

}
Sample Response

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Leaderboards v2 tutorials
5/24/2022 • 2 minutes to read • Edit Online

Getting Started
Child Leaderboards
Getting Started Tutorial
5/24/2022 • 3 minutes to read • Edit Online

IMPORTANT
This feature is currently in Private Preview .
This documentation is provided to give you an early look at an upcoming feature and to allow you to provide feedback
while it is still in development.
Access to this feature is restricted to select titles that PlayFab actively reaches out to.

Viewing Statistics
You can call GetLeaderboard to pull the current data on your leaderboard:

private static void getLeaderboard() {


//call an existing leaderboard
PlayFabLeaderboardsModels.GetEntityLeaderboardRequest getEntityLeaderboardRequest = new
PlayFabLeaderboardsModels.GetEntityLeaderboardRequest();

getEntityLeaderboardRequest.EntityType ="{{the type of the entity}}"; // Example:


title_player_account
getEntityLeaderboardRequest.MaxResults = Long.valueOf(10); // Want to see maximum the top 10
statistics ranked on the leaderboard
getEntityLeaderboardRequest.StatisticName = "{{Name of your leaderboard";

ArrayList<PlayFabLeaderboardsModels.EntityLeaderboardEntry> rankings
= PlayFabLeaderboardsAPI.GetLeaderboard(getEntityLeaderboardRequest).Result.Rankings;

//Do something about the result, such as:


rankings.forEach(ranking -> System.out.println(ranking.Rank + " " + ranking.Score));
}

You can also call GetStatisticDefinition to see how your leaderboard was configured:

private static void getLeaderboardInfo() {


PlayFabLeaderboardsModels.GetStatisticDefinitionRequest getStatisticDefinitionRequest = new
PlayFabLeaderboardsModels.GetStatisticDefinitionRequest();
getStatisticDefinitionRequest.Name = "{{the name of the leaderboard}}"; //fill in the name of your
leaderboard
PlayFabLeaderboardsModels.GetStatisticDefinitionResponse response
= PlayFabLeaderboardsAPI.GetStatisticDefinition(getStatisticDefinitionRequest).Result;

//Now you can do something with the response, or just simply printing them out for testing purposes:
System.out.println("Name: "+ response.Name);
System.out.println("AggregationMethod: "+ response.AggregationMethod);
System.out.println("Created: "+ response.Created);
System.out.println("LastResetTime: "+ response.LastResetTime);
System.out.println("ChildLeaderboardNames: "+ response.LeaderboardDefinition.ChildLeaderboardNames);
}

You can also see a list of all your leaderboard definitions by calling GetStatisticDefinitions :
private static void getAllDefs() {
PlayFabLeaderboardsModels.GetStatisticDefinitionsRequest getStatisticDefinitionsRequest = new
PlayFabLeaderboardsModels.GetStatisticDefinitionsRequest();
ArrayList<PlayFabLeaderboardsModels.StatisticDefinition> results =
PlayFabLeaderboardsAPI.GetStatisticDefinitions(getStatisticDefinitionsRequest).Result.StatisticDefinitions;
results.forEach(result -> System.out.println(result.Name));
}

GetLeaderboardAroundEntity lets you see entities ranked near a certain position on a leaderboard, namely, a
snapshot of a part of the leaderboard.

private static void getLeaderboardAroundEntity() {


PlayFabLeaderboardsModels.GetLeaderboardAroundEntityRequest req = new
PlayFabLeaderboardsModels.GetLeaderboardAroundEntityRequest();

// Define the entity to perform the call on


req.Entity = new PlayFabLeaderboardsModels.EntityKey();
req.Entity.Type = "title_player_account";
req.Entity.Id = "7FEDE4301B2C0D78";

req.StatisticName = "TaggedBasic"; // Name of the leaderboard


req.Offset = Long.valueOf(1); // How many entries above and below the current position of the entity
on the ranking

ArrayList<PlayFabLeaderboardsModels.EntityLeaderboardEntry> rankings =
PlayFabLeaderboardsAPI.GetLeaderboardAroundEntity(req).Result.Rankings;

// Do something about the response, such as:


rankings.forEach(ranking -> System.out.println(ranking.Rank + " " + ranking.Score));
}

Finally, it's useful sometimes to immediately see the ranks of select players on a leaderboard to gauge their
relative performance. The GetLeaderboardForEntities call accomplishes just that:

private static void getLeaderboardForEntities() {


PlayFabLeaderboardsModels.GetLeaderboardForEntitiesRequest getLeaderboardForEntitiesRequest = new
PlayFabLeaderboardsModels.GetLeaderboardForEntitiesRequest();
getLeaderboardForEntitiesRequest.Entities = new ArrayList<>();
getLeaderboardForEntitiesRequest.StatisticName = "{{name of the leaderboard}}";
getLeaderboardForEntitiesRequest.EntityType = "{{example: title_player_account}}";
getLeaderboardForEntitiesRequest.Entities.add("{{Id of the first entity}}"); //example:
F8A6093F4730C1B4
getLeaderboardForEntitiesRequest.Entities.add("{{Id of the second entity}}"); //repeat this line for
more entities if needed

ArrayList<PlayFabLeaderboardsModels.EntityLeaderboardEntry> rankings
=
PlayFabLeaderboardsAPI.GetLeaderboardForEntities(getLeaderboardForEntitiesRequest).Result.Rankings;
//do something about the result rankings, for example:
rankings.forEach(ranking -> System.out.println(ranking.Rank + " " + ranking.Score));

Deleting Statistics
Deleting statistics is a new feature in v2. You can delete an entire leaderboard as follows:
private static void deleteLeaderboard() {
PlayFabLeaderboardsModels.DeleteStatisticDefinitionRequest deleteStatisticDefinitionRequest = new
PlayFabLeaderboardsModels.DeleteStatisticDefinitionRequest();

deleteStatisticDefinitionRequest.Name = "{{the name of the leaderboard to delete}}";


PlayFabLeaderboardsAPI.DeleteStatisticDefinition(deleteStatisticDefinitionRequest);
}

Alternatively, you could delete a bunch of individual statistics for a single entity at once:

private static void deleteStatistics() {


PlayFabLeaderboardsModels.DeleteStatisticsRequest deleteStatisticsRequest = new
PlayFabLeaderboardsModels.DeleteStatisticsRequest();

ArrayList<PlayFabLeaderboardsModels.StatisticDelete> stats = new ArrayList<>();

// Define the first statistic you want to delete


// Repeat the next 3 lines of code for every statistic you want to delete
PlayFabLeaderboardsModels.StatisticDelete stat0 = new PlayFabLeaderboardsModels.StatisticDelete();
stat0.Name = "{{the name of a statistic you want to delete}}";
stats.add(stat0);

// Identify the entity you want to delete the statistics on


deleteStatisticsRequest.Entity = new PlayFabLeaderboardsModels.EntityKey();
deleteStatisticsRequest.Entity.Type = "{{the type of the entity}}"; // Example: title_player_account
deleteStatisticsRequest.Entity.Id = "{{the id of the entity}}"; //Example: D0B9D3D19E9A5557
deleteStatisticsRequest.Statistics = stats;
PlayFabResult<PlayFabLeaderboardsModels.DeleteStatisticsResponse> response =
PlayFabLeaderboardsAPI.DeleteStatistics(deleteStatisticsRequest);

//Optional: do something about the response


}

Leaderboard Versions
Say your game has a weekly tournament that produces new rankings of players, it is important to keep track of
the Version your leaderboard as it updates weekly. You can call IncrementStatisticVersion to increment the
version number (starts with 0) of your leaderboard.

private static void incrementVersion() {


PlayFabLeaderboardsModels.IncrementStatisticVersionRequest incrementStatisticVersionRequest = new
PlayFabLeaderboardsModels.IncrementStatisticVersionRequest();
incrementStatisticVersionRequest.Name = "{{name of leaderboard}}";
PlayFabResult<PlayFabLeaderboardsModels.IncrementStatisticVersionResponse> response =
PlayFabLeaderboardsAPI.IncrementStatisticVersion(incrementStatisticVersionRequest);

// If needed, you can get the current version number from the response
System.out.println("Version: " +response.Result.Version);
System.out.println("Deleted Version: " +response.Result.VersionToBeDeleted);
}

Keep in mind that you can't increment the version too frequently (less than 5 minutes) because it defeats the
purpose of having a leaderboard that everyone can see and engage with.
Child Leaderboard Tutorial
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
This feature is currently in Private Preview .
This documentation is provided to give you an early look at an upcoming feature and to allow you to provide feedback
while it is still in development.
Access to this feature is restricted to select titles that PlayFab actively reaches out to.

Child Leaderboards
Child Leaderboards are a new concept in v2. Now a Statistic can contain "children", or leaderboards that belong
to the same category. Adopting Child Leaderboards helps better organize leaderboards.
An example to help understand this concept is to imagine an array of game streaming rooms. Each room has a
list of viewers, who perform some actions to obtain a score. If the goal is to rank the viewers in each room, we
can create a Statistic that contains a child leaderboard for each room.
When you are creating a new Leaderboard, you can specify whether you want child leaderboards. If so, you need
to specify whether you want them to be Fixed or Dynamic:
Fixed Child Leaderboards
If you choose "Fixed", you can add up to 10 child leaderboards. Note that you won't be able to add more once
the parent Statistic is created. Although the maximum number of fixed child leaderboards is 10, you are allowed
to have very large child leaderboards under this option. You can visualize the parent leaderboard under this
option as fairly deep.
Dynamic Child Leaderboards
If you choose "Dynamic", you will need to specify the maximum size of your individual child leaderboards. You
can rank at most 100 items on each child leaderboard. Note that this size limit is maximum size of each
individual child leaderboard, not the total number of child leaderboards that you are allowed to have.
You can add child leaderboards "on-the-go" after you create your parant Statistic. While you are limited to
having a small number of rankings on each child leaderboard, you are allowed to have a lot of child
leaderboards in parallel. You can visualize the parent leaderboard under this option as fairly wide.
Economy
5/24/2022 • 3 minutes to read • Edit Online

Making your economy work is one of the biggest challenges in games. You need to balance between what can
be earned in game and what can be purchased, while supporting both highly engaged players and those with
light engagements. You want to support different store placements and sales events based on player segments.

NOTE
You can learn more about the preview User Generated Content (UGC) service in the User Generated Content
documentation

Key concepts
Catalog - Catalogs offer an easy way to manage your game's virtual items. They are listings of every item
that is available in your game.
Catalog Items – PlayFab Items can represent just about any type of virtual good that you might use, from
Durables, to Bundles to Locked containers.
Inventor y - All accounts (player accounts and character accounts) have an inventory. The inventory contains
all owned Item Instances as well as item history.
Segments - Provides subsets of players grouped by their event history. For example, the "Frequent Players"
segment is comprised of players that have logged in more than 100 times.
Stores - Stores serve a subset of Catalog Items; these items can be offered at alternative prices when
compared to those set on the corresponding Catalog Items.
Vir tual Currency - PlayFab offers up to 10 virtual currencies per title. Currencies can be used to purchase
Items from the Catalog or a Store, can represent soft currency converted from In App Purchases, or can be
used as a mechanic to drive gameplay.
PlayFab helps you build out your economy by providing a suite of tools to support game economy best
practices. These include:
Multiple Currencies : Most games support at least two virtual currencies. Many use a “soft” currency
that can be earned in-game through play, and a “hard” currency that can be bought. Having dual
currencies gives you more control over your economy, since you can determine which items can be
bought. See our tutorial on Currencies.
Ser ver-side receipt validation : To prevent fraud and ensure that the money you think you are making
is, in fact, being made. See our Getting Started with In App Purchasing and our Non-Receipt Payment
Processing tutorials.
Gathering Data on your economy : See our Reports section for tutorials on how to measure
Conversion, and create Daily and Monthly top Items and Spender reports.
Bundles : Generally, Bundles generate more revenue per transaction, and players feel they are getting a
great deal. You can use our Catalog to create and sell bundles of virtual goods. See our Catalog tutorial
for more information on how to create and leverage Bundles.
Segmentation : Your players are different, so you don't treat them all the same. With PlayFab you can
design your store to offer different items and bundles to different player segments, promoting different
items as players progress through your game and their play life-cycle. See our Custom Stores for player
segments and Best practices for store segmentation tutorials.
Sales : You may want to run special sales as part of your events, use limited time discounts, or have
limited-time offers for rare items. See our Stores and Sales tutorials for tips on how to manage these.
A/B Testing : Stores are also great opportunities for A/B testing. Try mixing up the order of items in the
store - the same item will sell differently depending on where it is and how it is displayed. See our tutorial
on A/B testing with Stores and Test Buckets.
Coupons : Special coupons that players can give to friends or share via social media can drive sales and
encourage viral growth. PlayFab supports coupons specifically for this sort of scenario: Coupons and
Promotions.
User Generated Content : Empower players to create, upload and search for moderated content. See
our UGC Quickstart for more information on how to begin using PlayFab UGC.
Economy quickstart
5/24/2022 • 3 minutes to read • Edit Online

Making monetization work is one of the biggest challenges in games. PlayFab simplifies this for you, by building
on top of three foundational pieces: Currencies, Items, and Inventory.
In this quickstart, you will:
1. Set up a virtual currency.
2. Create an item.
3. Add an item to a player's inventory.
4. Learn the next steps for customizing your economy.

Setting up a virtual currency


Virtual currencies are the foundation of in-game economies. Players and characters can be granted these
currencies, which can then be used to buy or trade items.
Items can have a cost in either a virtual currency or real money. Each title can support multiple arbitrary virtual
currencies. This provides flexibility for your game to implement whatever medium of exchange you desire (for
example, gold, gems, hearts, or interstellar credits).
To create a virtual currency:
1. Open Game Manager and select Economy on the left side bar.
2. Select the Currency tab.
3. Choose New Currency and change these fields (as shown in the image below):
Set Currency code (2 uppercase characters) to GD .
Set Display name to Gold .
4. Select SAVE CURRENCY .

Now that a currency has been set up, catalog items can be assigned prices corresponding to the virtual currency.

Creating an item
Many games offer the player items for purchase such as a shield, a level-unlock, or a power-up. These items are
specified in a catalog. Before the player can purchase an item from a catalog, you must create the items to
populate it.
To create a catalog with an item:
1. Select Economy on the left side bar and select the Catalogs tab.
2. Choose the NEW CATALOG button and enter main as the Catalog version . An item with the ID of One
is added automatically.
3. Select One and change these fields (as shown in the image below):
Set Item ID to apple .
Set Display name to apple .
Set Description to Perfectly normal apple .
4. At the bottom of the form is the PRICES section, where you define how much an item costs in your
game's virtual currency.
5. Set the apple's price in gold (GD ) to 5 .
6. Select the SAVE ITEM button.

Adding an item to a player inventory


PlayFab's Player Item Management (Server) and Player Item Management (Client) APIs support many strategies
for item purchasing, such as simple real money or virtual currency purchases of items, triggered item grants
based on buying another item, locked (with a potentially purchasable key) and unlocked boxes, random result
tables, and non-purchasable items that are granted based on events within a game.
Let's use the PlayFab APIs to add an item to a player's inventory by purchasing it with virtual currency.
1. In your game, log in as a player that has been given virtual currency. (Giving virtual currency to a player
has more information, if needed.)
2. Call GetCatalogItems with the following parameter in the request:
CatalogVersion = "main"
3. Verify that the Catalog in the result contains an apple with a GD price of 5 .
4. Call PurchaseItem to buy the apple , with these parameter values in the request:
CatalogVersion = "main"
ItemId = "apple"
VirtualCurrency = "GD"
Price = 5
5. Finally, call GetUserInventory and look in the result of that method. In the array of items in the player's
Inventory - you should see an apple!

Next Steps for customizing your economy


Once you have a Catalog with Items supported by Virtual Currencies, you can light up your economy with:
Real World Purchases : Our Getting started with PlayFab, Unity IAP, and Android and our Non-receipt
payment processing tutorials help you connect your virtual economy with existing stores.
Leveraging your Catalog : To create Bundles, Containers and Drop Tables. For more information, see our
Catalogs tutorial.
Using Item attributes : To define multiple prices and specify stackable, tradable, and limited edition Items.
Setting up unique in-game vendors or Sales events : Using Stores and Sales.
Creating some player Segments and use Stores : To drive different item and bundle offers to your
players regardless of where they are in your game lifecycle. For an example, see our Custom stores for player
segments tutorial.
Verifying your assumptions : Using A/B testing.
Gathering economic data : Enabling you to improve and iterate your game using PlayFab Reports.
Economy Tutorials
5/24/2022 • 2 minutes to read • Edit Online

These tutorials demonstrate features that you can use to create and maintain the economy of your game.
Coupons and Promotions
Currencies
Getting a Player's Value-to-Date (VTD)
Getting started with PlayFab, Unity IAP, and Android
Non-Receipt Payment Processing
Coupons and promotions
5/24/2022 • 3 minutes to read • Edit Online

Coupons are string tokens that are generated by you, for your customers use to redeem inventory items in their
game. Combined with bundles or CloudScript, these coupons could be used to trigger almost any functionality
in your game.

Requirements
Familiarity with Catalogs, bundles, and containers.
Familiarity with Game Manager.
Familiarity with Player Inventory.

Generate and redeem coupon instructions


All of the examples that follow share the first basic step of generating a coupon. This is done in Game Manager.
From your Game Manager :
Navigate to your Title .
Select Economy from the menu to the left.
Go to your Catalogs tab.
For any of the three tab-sections: Items , Bundles , and Containers , you will find a Coupons link.

This opens a window, which lets you generate coupons for any of the items in the section. If you wish to create
coupons for a specific item:
Select Coupons in the Items tab.
Bundle Coupons under Bundles , and Container Coupons under Containers .
The pop-up window is similar to the one we have provided below. (Your list of items will match your title. The
displayed items are described in our Drop Tables tutorial).

To complete the coupon generation:


Select a quantity of Coupons to generate.
Then select the Item the Coupons should generate.
This will download a CSV text file with a list of Coupons .
Selecting one of the links in the example generates the following ten comma-separated Coupons .

65g-d4q5-zph,ahs-aofk-5ip,rqp-pk6c-yuu,58d-64h9-a6q,zxk-jtmi-5a1,oeu-6e4z-365,mfy-euhb-qj3,ru9-r1ux-wzy,shj-
54cm-5oh,719-7hxc-pzz

Finally, the customer can redeem a coupon if you provide a GUI which lets them input the code, which then calls
RedeemCoupon.
// Unity/C#
void UseCoupon(string couponCode)
{
var primaryCatalogName = "TestCatalog-001"; // In your game, this should just be a constant matching
your primary catalog
var request = new RedeemCouponRequest
{
CatalogVersion = primaryCatalogName,
CouponCode = couponCode // This comes from player input, in this case, one of the coupon codes
generated above
};
PlayFabClientAPI.RedeemCoupon(request, LogSuccess, LogFailure);
}

Example case: Inventory item coupon


The most straightforward way to use coupons is gifting an inventory item. Once you have created your catalog,
you can generate coupons for regular items by following the previous instructions we have already discussed.
There are no other special steps for this case.
Example case: Virtual currency coupon or multiple item coupon
Coupons cannot grant Virtual Currency directly, and they can only grant a single item.
However, bundles can be used to convert inventory items seamlessly into groups of items or virtual currency. In
the VC example, you should create a new bundle item, with VC contents.
Set the bundle to expire in 15 seconds . This way, the player will immediately see the VC as soon as they open
the bundle, and they won't see the intermediate item.

Multiple items work the same way:


Create a bundle with multiple items - or even Drop Tables.
Set it to expire in 15 seconds .
The coupon can generate the bundle.
The bundle is then converted to multiple items.
The intermediate bundle item disappears.

Usage scenarios
Physical rewards at conventions:
Print out your list of coupon codes, and hand them out as swag at conventions.
Out-of-game communication such as forums, Push Notifications and email.
Send your players coupon codes directly, as part of re-acquisition campaigns or other community
outreach.
Tournaments:
Send coupons to the top ranked players when using Resettable Leaderboards.

NOTE
You can also give out inventory items directly in this case, so pick whichever is more relevant to your game.

Best practices
Using the PlayFab inventory, you should keep inventory sizes relatively small - less than 100 items total per
player. A bundle which grants too many items may be throttled or rate-limited.
Currencies
5/24/2022 • 3 minutes to read • Edit Online

This tutorial describes the function of the Currency tab in the Economy section in Game Manager . Use this
tab to configure virtual currencies to use in your game.
Virtual Currencies are the foundation of in-game economies. Players and characters can be granted these
currencies, which they can use to buy or trade items. Items have a cost in either virtual currency or real money.
It's exactly like real life - except it's virtual! Economic regulation in-game is up to you.

What is virtual currency?


Virtual currencies provide a medium of exchange for players to purchase virtual items and services from within
a title.
Each title can support multiple arbitrary virtual currencies. This provides flexibility for your game to implement
any medium of exchange you desire (e.g. gold, gems, hearts or interstellar credits).
After the initial setup, store and catalog items can be assigned prices corresponding to the virtual currencies.
Our Game Manager provides tools to make managing your virtual economy straightforward and reliable.

Field reference
This section describes each field in the Currency section of the Economy area in Game Manager . The
following are the fields in the New Currency screen (shown below), which you'll use to create and maintain the
virtual currencies that make up your in-game economy.
Currency code and Display name are required fields with no default values. The other fields have a
default value of zero .
Leaving Recharge rate and Recharge maximum set to zero (default) will specify that this currency
amount will not auto-regenerate.

Currency code
Currency code is a required field. It represents the currency, and will be used in the other economy sections.
It must be a two-character code, and the convention is all upper-case (although a two-digit number is also
allowed).
NOTE
RM is reserved for Real Money and cannot be used as a Currency Code.

Display name
Display name is a required field. It represents the name that is attached to the currency that is typically
displayed to the user in your game.
The only restriction is that it must be at least one letter long. Common examples include Gold or Space Bux .
Initial deposit
Initial deposit indicates how much of this virtual currency is given to each player when they first sign-up for a
PlayFab account (which is typically the first time they play your game).
Recharge rate (units per day)
Recharge rate is an optional field. It specifies how much of this virtual currency is granted to each player per
day. Virtual currency that is granted to the player via a recharge rate is granted to them gradually, and is evenly
distributed over a 24 hour period.
Recharge maximum
Recharge maximum is an optional field. It specifies the maximum amount of this virtual currency that can be
granted to each player per day.

Example
To create a virtual currency, use the following steps:
1. Select your Game in Game Manager .
2. Choose Economy .
3. Select Currency .
4. Choose NEW CURRENCY .
5. Set the Currency code . We'll use GD in this example.
6. Set the Display name . We'll use Gold in this example.
7. Set the Initial deposit . We'll use 1000 in this example. This gives new players 1,000 units of this virtual
currency when they begin the game.
8. By leaving the Recharge rate and Recharge maximum at the default value of 0 - we don't give the players
any additional virtual currency every day, so we're done.
9. Select SAVE CURRENCY .
This returns you to the Currencies screen where you will see that your new virtual currency is added.
For any subsequent operations on your currency, such as deleting, renaming, or modifying the recharge values,
select the Code or Display name of your currency to open the Edit Currency screen.
The grayed-out Currency code means your new currency has been saved.
Getting a player's Value-to-Date (VTD)
5/24/2022 • 2 minutes to read • Edit Online

PlayFab tracks the total amount spent by a player in the player profile model, which is retrieved by calling the
GetPlayerProfile API.
Within the PlayerProfileModel , a player's VTD is tracked in two different fields:
1. totalValueToDateInUSD - The sum of the player's purchases made with real-money currencies, converted to
the US dollars (USD ) equivalent and represented as a whole number of cents (1/100 USD).
2. valuesToDate - An array of ValueToDateModel objects that contain the player's lifetime purchase totals,
summed for each real-money currency in which they have made a purchase. The TotalValue field in each
object expresses the total for that currency as a whole number of 1/100 monetary units.
The following JSON, shows these two fields with example values.

{

totalValueToDateInUSD: 1700
valuesToDate: [{ "USD", 1200 }, { "EUR", 320 }]

}

Using VTD to define player segments


In the PlayFab Game Manager, you can use either of the VTD totals described above as segment predicates -
criteria that can be used to define player segments.
When you are creating or editing a player segment, you will see the two predicates (listed below) included in the
dropdown list:
1. Total value to date in USD - The TotalValueToDateInUSD value.
2. Value to date - The ValuesToDate totals. When you select this predicate, you will see additional fields to
specify the currency and the amount for that currency.

Segment examples
The following examples show segments created using each of the VTD totals.
1. Create a segment of all players who have purchased more than 15 USD in any currency.

2. Create a segment of all players who have spent more more than 15 USD in any currency or 15 Chinese
Yuan .
Getting started with PlayFab, Unity IAP, and Android
5/24/2022 • 10 minutes to read • Edit Online

This tutorial shows you how to set up In-App Purchasing (IAP) using PlayFab, the Unity + IAP Service, and the
Android Billing API.

Before we start
Setting up IAP may be tedious, especially if you are not quite sure how different services are supposed to
integrate and cooperate.
The following image illustrates how the Android Billing API and PlayFab work together to provide a solid IAP
experience for your client.

Start by setting up your Product IDs and Prices via PlayMarket. Initially, all the products are faceless - they are
just digital entities your player is able to purchase - but they have no meaning to PlayFab players.
To make those entities useful, we need to mirror them in the PlayFab item catalogs. This will turn faceless entities
into bundles, containers, and individual items.
Each will have their own unique face, with:
Titles
Descriptions
Tags
Types
Images
Behaviors
All of these are linked to market products by sharing IDs.
The best way to access real money items available for purchase is to use GetCatalogItems and GetStoreItems.
These are the same API methods that are used by free-currency stores, so the process should be familiar.
The ID of the item is the link between PlayFab and any external IAP system. So we pass the item ID to the IAP
service.
At this point, the purchase process begins. The player interacts with the IAP interface and - if the purchase is
successful - you obtain a receipt.
PlayFab is then able to validate the receipt and register the purchase, granting the PlayFab player the items that
they just bought.
This is a rough idea of how IAP integration works, and the following example shows most of it in action.

Setting up a client application


This section shows you how to configure a very primitive application to test IAP using PlayFab, UnityIAP, and the
Android Billing API.
Prerequisites:
A Unity project.
The PlayFab SDK imported and configured to work with your title.
Our first step is setting up UnityIAP:
1. Navigate to Ser vices .
2. Make sure the Ser vices tab is selected.
3. Select your Unity Ser vices profile or organization.
4. Select the Create button.
1. Next, navigate to the In-App Purchasing (IAP) service.
1. Make sure to enable the Ser vice , by setting the Simplify cross-platform IAP toggle.
2. Then select the Continue button.
A page with a list of plugins will appear.
1. Select the Impor t button.

Continue the Unity install, and import procedure up to the point where it has imported all the plugins.
1. Verify that the plugins are in place.
2. Then create a new script, called AndroidIAPExample.cs .

AndroidIAPExample.cs will contain the code shown below (please refer to the code comments for further
explanation).

using PlayFab;
using PlayFab.ClientModels;
using PlayFab.Json;
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Purchasing;
public class AndroidIAPExample : MonoBehaviour, IStoreListener {
// Items list, configurable via inspector
private List<CatalogItem> Catalog;

// The Unity Purchasing system


private static IStoreController m_StoreController;

// Bootstrap the whole thing


public void Start() {
// Make PlayFab log in
Login();
}

public void OnGUI() {


// This line just scales the UI up for high-res devices
// Comment it out if you find the UI too large.
GUI.matrix = Matrix4x4.TRS(new Vector3(0, 0, 0), Quaternion.identity, new Vector3(3, 3, 3));

// if we are not initialized, only draw a message


if (!IsInitialized) {
GUILayout.Label("Initializing IAP and logging in...");
return;
}

// Draw menu to purchase items


foreach (var item in Catalog) {
if (GUILayout.Button("Buy " + item.DisplayName)) {
// On button click buy a product
BuyProductID(item.ItemId);
}
}
}

// This is invoked manually on Start to initiate login ops


private void Login() {
// Login with Android ID
PlayFabClientAPI.LoginWithAndroidDeviceID(new LoginWithAndroidDeviceIDRequest() {
CreateAccount = true,
AndroidDeviceId = SystemInfo.deviceUniqueIdentifier
}, result => {
Debug.Log("Logged in");
// Refresh available items
RefreshIAPItems();
}, error => Debug.LogError(error.GenerateErrorReport()));
}

private void RefreshIAPItems() {


PlayFabClientAPI.GetCatalogItems(new GetCatalogItemsRequest(), result => {
Catalog = result.Catalog;

// Make UnityIAP initialize


InitializePurchasing();
}, error => Debug.LogError(error.GenerateErrorReport()));
}

// This is invoked manually on Start to initialize UnityIAP


public void InitializePurchasing() {
// If IAP is already initialized, return gently
if (IsInitialized) return;

// Create a builder for IAP service


var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance(AppStore.GooglePlay));

// Register each item from the catalog


foreach (var item in Catalog) {
builder.AddProduct(item.ItemId, ProductType.Consumable);
}

// Trigger IAP service initialization


// Trigger IAP service initialization
UnityPurchasing.Initialize(this, builder);
}

// We are initialized when StoreController and Extensions are set and we are logged in
public bool IsInitialized {
get {
return m_StoreController != null && Catalog != null;
}
}

// This is automatically invoked automatically when IAP service is initialized


public void OnInitialized(IStoreController controller, IExtensionProvider extensions) {
m_StoreController = controller;
}

// This is automatically invoked automatically when IAP service failed to initialized


public void OnInitializeFailed(InitializationFailureReason error) {
Debug.Log("OnInitializeFailed InitializationFailureReason:" + error);
}

// This is automatically invoked automatically when purchase failed


public void OnPurchaseFailed(Product product, PurchaseFailureReason failureReason) {
Debug.Log(string.Format("OnPurchaseFailed: FAIL. Product: '{0}', PurchaseFailureReason: {1}",
product.definition.storeSpecificId, failureReason));
}

// This is invoked automatically when successful purchase is ready to be processed


public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs e) {
// NOTE: this code does not account for purchases that were pending and are
// delivered on application start.
// Production code should account for such case:
// More: https://docs.unity3d.com/ScriptReference/Purchasing.PurchaseProcessingResult.Pending.html

if (!IsInitialized) {
return PurchaseProcessingResult.Complete;
}

// Test edge case where product is unknown


if (e.purchasedProduct == null) {
Debug.LogWarning("Attempted to process purchase with unknown product. Ignoring");
return PurchaseProcessingResult.Complete;
}

// Test edge case where purchase has no receipt


if (string.IsNullOrEmpty(e.purchasedProduct.receipt)) {
Debug.LogWarning("Attempted to process purchase with no receipt: ignoring");
return PurchaseProcessingResult.Complete;
}

Debug.Log("Processing transaction: " + e.purchasedProduct.transactionID);

// Deserialize receipt
var googleReceipt = GooglePurchase.FromJson(e.purchasedProduct.receipt);

// Invoke receipt validation


// This will not only validate a receipt, but will also grant player corresponding items
// only if receipt is valid.
PlayFabClientAPI.ValidateGooglePlayPurchase(new ValidateGooglePlayPurchaseRequest() {
// Pass in currency code in ISO format
CurrencyCode = e.purchasedProduct.metadata.isoCurrencyCode,
// Convert and set Purchase price
PurchasePrice = (uint)(e.purchasedProduct.metadata.localizedPrice * 100),
// Pass in the receipt
ReceiptJson = googleReceipt.PayloadData.json,
// Pass in the signature
Signature = googleReceipt.PayloadData.signature
}, result => Debug.Log("Validation successful!"),
error => Debug.Log("Validation failed: " + error.GenerateErrorReport())
);

return PurchaseProcessingResult.Complete;
}

// This is invoked manually to initiate purchase


void BuyProductID(string productId) {
// If IAP service has not been initialized, fail hard
if (!IsInitialized) throw new Exception("IAP Service is not initialized!");

// Pass in the product id to initiate purchase


m_StoreController.InitiatePurchase(productId);
}
}

// The following classes are used to deserialize JSON results provided by IAP Service
// Please, note that JSON fields are case-sensitive and should remain fields to support Unity
Deserialization via JsonUtilities
public class JsonData {
// JSON Fields, ! Case-sensitive

public string orderId;


public string packageName;
public string productId;
public long purchaseTime;
public int purchaseState;
public string purchaseToken;
}

public class PayloadData {


public JsonData JsonData;

// JSON Fields, ! Case-sensitive


public string signature;
public string json;

public static PayloadData FromJson(string json) {


var payload = JsonUtility.FromJson<PayloadData>(json);
payload.JsonData = JsonUtility.FromJson<JsonData>(payload.json);
return payload;
}
}

public class GooglePurchase {


public PayloadData PayloadData;

// JSON Fields, ! Case-sensitive


public string Store;
public string TransactionID;
public string Payload;

public static GooglePurchase FromJson(string json) {


var purchase = JsonUtility.FromJson<GooglePurchase>(json);
purchase.PayloadData = PayloadData.FromJson(purchase.Payload);
return purchase;
}
}

1. Create a new Game object called Code .


2. Add the AndroidIAPExample component to it (2-step process).
3. Add the AndroidIAPExample component to it.
4. Make sure to Save the scene.
Finally, navigate to Build Settings .
1. Verify that your scene has been added to the Scenes In Build area.
2. Make sure that the Android platform has been selected.
3. Move to the Player Settings area.
4. Assign your Package Name .

NOTE
Make sure to come up with your own package name to avoid any PlayMarket collisions.
Finally, build the application as usual, and ensure you have an APK safe and sound.
We have no means to test it just yet. We need to configure PlayMarket and PlayFab first, which is described in
the following sections.

Setting up a PlayMarket application for IAP


This section describes the specifics of how to enable IAP for your PlayMarket application.

NOTE
Setting up the application itself is beyond the scope of this tutorial. We assume you already have an application, and that
is configured to publish at least Alpha releases.

Useful notes:
Getting to that point will require you to have an APK uploaded. Please use the APK we constructed in the
previous section.
When asked to upload the APK, you may upload it as an Alpha or Beta Application to enable the IAP sandbox.
Configuring Content Rating will include questions about how IAP is enabled in the application.
PlayMarket does not allow Publishers to use or test IAP - so please, pick another Google account for testing
purposes, and add it as a tester for your Alpha/Beta build.
Once you have the application build published:
1. Select In-app products from the menu.
If you are asked for a Merchant Account , link or create one.
2. Select the Add New Product button.

1. On this screen shown below, select Managed Product .


2. Give it a descriptive Product ID .
3. Select Continue .

PlayMarket requires you to fill in a Title (1) and a Description (2) . However, these are not much use in our
case.
We will grab Data Item data exclusively from the PlayFab service, and only require IDs to match.
1. Scroll further and select the Add a price button.

1. Enter a valid price (notice how price is converted for each country/region independently).
2. Select the Apply button.
1. Finally, scroll back to the top of your screen, and change the status of the item to Active .

While this concludes configuring the app, we need a couple more tweaks. First, let us save the Licensing Key
(this will come in handy for linking PlayFab with PlayMarket.
1. Navigate to Ser vices & APIs in the menu.
2. Then locate and save the Base64 version of the Key .
The next step is enabling IAP testing. While sandbox is automatically enabled for Alpha and Beta builds, we need
to set up accounts that are authorized to test the app:
1. Navigate to Home .
2. Locate and select the Account details in the menu to the left.
3. Locate the License Testing area.
4. Verify that your Test Accounts are in the list.
5. Make sure the License Test Response is set to RESPOND_NORMALLY .
Don't forget to apply the settings!
The Play Market side of the integration should be set up at this point.

Setting up a PlayFab title


Our last step is configuring a PlayFab title to reflect our products, and integrate with the Google Billing API.
1. Select Add-ons .
2. Then, select the Google add-on.

1. Fill in your Package ID .


2. Fill in the Google App License Key that you acquired in the previous section.
3. Commit your changes by selecting the Install Google button.
Our next step is reflecting our Golden Sword item in PlayFab:
1. Select Economy .
2. Verify that the Catalogs sub-tab is selected.
3. Select New Catalog .
4. Provide a Catalog version name.
5. Select Save Catalog .
If the catalog has no items, it is automatically removed. That's why any new catalog comes with a pre-added
item called One .
We can always create a new item, but to keep things clean, let's modify the existing One item.
1. Select the item to edit the Item ID to match the ID in PlayMarket.
2. Now, edit the Display name and add a Description .

NOTE
Keep in mind that this data has nothing to do with the Play Market Item Title and Description - it is totally
independent.

3. Assign a Price to your Item .


4. Select Save Item to commit your changes.
NOTE
In this tutorial, IAP mainly refers to purchases for real money. That's why we use RM - special Real Money currency. The
PlayFab amount is defined in US Cents.

5. Observe your item in the Item ID list.

This concludes the setup for your PlayFab title.

Testing
For testing purposes, download the app using the Alpha/Beta release.
Make sure to use a test account and a real Android device.
Once you start the app, you should see IAP initialized, and one button representing your item.
Select that button.
The IAP purchase will be initiated. Follow the Google Play instruction up to the point where purchase is
successful.

Finally, navigate to your title in the PlayFab Game Manager dashboard and locate New Events .

This means that purchase was successfully provided, validated, and piped to the PlayFab ecosystem.
At this point you have successfully integrated UnityIAP and the Android Billing API into your PlayFab application.
Non-receipt payment processing
5/24/2022 • 14 minutes to read • Edit Online

In addition to receipt validation for a variety of platforms, PlayFab also provides a mechanism for enabling
purchases via payment providers that don’t use a receipt or entitlement-based systems - such as Facebook,
PayPal, Xsolla, and Steam.
This tutorial will walk you through using this cart-style payments system, showing you how to:
Define the set of goods the player wants to purchase.
Process the player with your chosen provider.
Validate that the payment processed successfully, adding the appropriate items to the player’s inventory.
In addition, it will also cover the player provider part of the process, so that you have a complete
overview of how to complete the purchase using PlayFab.
The following image shows a summary of the API calls used in the payment flow.

Setting up payment providers


Before we begin with the logic for actually processing payments, the first thing you’ll need to do is to actually set
up your intended payment providers.
To do that:
Choose your game in the PlayFab Game Manager.
Select the Add-ons tab.
That takes you to our Add-ons Marketplace , where you can find all our third-party integrations, including
Payment Providers .

NOTE
Some providers, like Facebook and Steam, do more than just handle payments, and you’ll find them in the Platforms
section of this tutorial.
Select the Providers you want to use.
Then choose the Install option for each.
Enter the requested information (commonly an application and secret key), but each provider will have their
own unique requirements.

NOTE
This information allows us to communicate with their service on your behalf, so that we can initiate purchases and check
on their status.

Once that has been completed, you’re ready to start implementing the payment flow.

PlayFab API calls


From the client, the sequence of calls for this process are very similar for most non-receipt payment providers.
StartPurchase - Creates the list of goods for the purchase.
PayForPurchase - Establishes the payment provider and locks the payment pricing.
ConfirmPurchase - Validates whether the purchase completed successfully and if necessary ensures the
goods are added to the player’s inventory.

NOTE
The exception to this is Xsolla, which we'll address separately at the end of this tutorial.

In the examples that follow, you’ll see fields like {{TitleID}} and {{SessionTicket}} . You will need to replace
these values in your own code, with the appropriate values for your game, and the player’s authentication ticket.

Initiating the purchase


Throughout the purchase flow, you’ll be working with a defined set of goods from your game catalog that the
player wants to purchase.
This is the cart of goods, which you define by a call to PlayFab Client API method StartPurchase , to start the
process.

PlayFabClientAPI.StartPurchase(new StartPurchaseRequest() {
CatalogVersion = "IAP1_0",
Items = new List<ItemPurchaseRequest>() {
new ItemPurchaseRequest() {
ItemId = "BigBagOfGold",
Quantity = 1,
Annotation = "Purchased via in-game store"
}
}
}, result => {
// Handle success
}, error => {
// Handle error
});

In this example, we’re loading up the cart with an item defined in the game catalog with the ID of IAP1_0 -a
BigBagOfGold . This is the ItemId , as defined in the game catalog.

The player wants to purchase only one of it, and the annotation is being used to indicate how the item wound up
in the player inventory, which is useful for later review.
It’s also possible to specify that this purchase is using the pricing from a store you’ve defined in your game, by
including the StoreId parameter, but we’ll leave that out of this example, for simplicity.
The return from the StartPurchase call contains a lot of information - including the DisplayName and
Description values for the items from your catalog, any defined prices for them, plus the player's virtual
currency balances.
But the primary things you’ll need for the next step are the OrderId (which uniquely identifies this purchase),
and the specific provider you want to use, which is in the PaymentOptions .

NOTE
Only Payment Providers you have enabled for your title will appear in the PaymentOptions .

{
"code": 200,
"status": "OK",
"data": {
"OrderId": "1234567890ABCDEF",
"Contents": [{
"ItemId": "BigBagOfGold",
"ItemInstanceId": "ABCDEF1234567890",
"DisplayName": "A hefty sack of gold",
"Description": "Why, it’s a stonking great bag of shiny!",
"VirtualCurrencyPrices": {
"RM": 999
}
}],
"PaymentOptions": [{
"Currency": "RM",
"ProviderName": "Facebook",
"Price": 999,
"StoreCredit": 0
},
{
"Currency": "RM",
"ProviderName": "PayPal",
"Price": 999,
"StoreCredit": 0
},
{
"Currency": "RM",
"ProviderName": "Steam",
"Price": 999,
"StoreCredit": 0
}
],
"VirtualCurrencyBalances": {
"VC": 0
}
}
}

Establishing the payment provider: Webhook providers


Facebook
Normally, the flow at this point is to tell PlayFab which payment providers will be used, so that the service can
communicate with that provider and set up the information about the transaction.
Facebook is an exception to this procedure. It requires that the purchase be initiated in their service first. After
that, a third-party service such as PlayFab can use the Facebook-provided transaction identifier to validate the
status of the purchase.
If your store, catalog, or item IDs are not alpha-numeric, they must be HTML / URL encoded when building the
OpenGraphProduct URL, as shown in the following code.

FB.ui({
method: 'pay',
action: 'purchaseitem',
product:
"https://{{TitleId}}.playfabapi.com/OpenGraphProduct/{{TitleId}}/{{StoreId}}/IAP1_0/BigBagOfGold",
request_id: "1234567890ABCDEF"
}, function (response) {
console.log('Payment completed', response);
print(response);
if (response.payment_id) {
facebookPurchaseId = response.payment_id;
payForOrder(); // This is a function call you need to write
// which makes the call to the Client API PayForPurchase
// (see below)
}
});

When making this call, lease remember that the product is case-sensitive in Facebook.
In particular, the TitleId - which you need to replace with the correct title ID for your game in PlayFab - is
usually in lower-case in their service. If you encounter any issues with Facebook not finding the correct product,
try grabbing the product manually using a GET request, as shown on this page.
In addition, you’ll also need to make sure you’re using the values from earlier in the flow:
The CatalogID of the PlayFab-defined catalog containing the item to be purchased ( IAP1_0 ).
The itemID of the item in the game’s PlayFab catalog which is to be purchased ( BigBagOfGold )
The OrderID returned from the call to StartPurchase , at the beginning of this process ( 1234567890ABCDEF
)
On a successful response, Facebook will return a payment_id , which can then be used as the
ProviderTransactionId in the call to the Client API method PayForPurchase .

const string paymentId = "_SOME_PAYMENT_ID" ;


PlayFabClientAPI.PayForPurchase(new PayForPurchaseRequest() {
OrderId = "1234567890ABCDEF",
ProviderName = "Facebook",
Currency = "RM",
ProviderTransactionId = paymentId
}, result => {
// Handle success
}, error => {
// Handle error
});

Which should return a simple confirmation.


{
"code": 200,
"status": "OK",
"data": {
"OrderId": "1234567890ABCDEF",
"Status": "Init",
"PurchaseCurrency": "RM",
"PurchasePrice": 999,
"CreditApplied": 0
}
}

This completes the loop, connecting PlayFab to the purchase on both sides of the equation, allowing us to query
for its status.
You can read more about the Facebook payment system on the Facebook Developer Portal:
https://developers.facebook.com/docs/payments/overview
An additional aspect of Facebook Payments is that there is a requirement that titles use webhooks for payments,
to enable real time change notifications to payment status.
This is necessary in the Facebook model, as payments can take a very long time to complete in some cases.
Fortunately, this is simple. In your title setup in Facebook, simply enter the following as your Callback URL.

https://{{TitleId}}.playfabapi.com/ThirdPartyPayments/FacebookPaymentUpdate

Where {{TitleId}} is the Title ID for your game in PlayFab (for example,
https://aaa.playfabapi.com/ThirdPartyPayments/FacebookPaymentUpdate).
There’s no need to specify a token in the Facebook setup - just set the Callback URL, confirm that your PlayFab
setup is correct in the Facebook Add-ons page of the Game Manager , and you’re set.
When Facebook uses this webhook to update the status of the payment, the order status will be updated in
PlayFab (and if it was successful), the appropriate items will be added to the player inventory.

NOTE
Security: Be aware that this API is a prompt for PlayFab to call again to Facebook, and securely authenticate and validate
the transaction. It is not a backdoor for a hacker to bypass Facebook payments.

When using Facebook as the payment provider, it is still important for your client to confirm the purchase, as
shown below.

Establishing the payment provider: Non-webhook providers


Steam
Steam is the easiest to integrate of all the payment providers.
PlayFabClientAPI.PayForPurchase(new PayForPurchaseRequest() {
OrderId = "1234567890ABCDEF",
ProviderName = "Steam",
Currency = "RM"
}, result => {
// Handle success
}, error => {
// Handle error
});

As a result of the PayForPurchase call, PlayFab uses the web methods provided by Steam to initiate the purchase
in that service. This automatically causes the user to be presented with the purchase confirmation dialog via the
Steam client.
So at the same time you’re getting the response to the Client API PayForPurchase call, the user is being asked to
accept the payment.

{
"code": 200,
"status": "OK",
"data": {
"OrderId": "1234567890ABCDEF",
"Status": "Init",
"PurchaseCurrency": "RM",
"PurchasePrice": 999,
"CreditApplied": 0
}
}

Steam uses a callback mechanism to inform the title of completion of the purchase process, so you will need to
register a callback handler for the MicroTxnAuthorizationResponse_t callback.
Registered Steam developers can get further information on this process at this location:
https://partner.steamgames.com/documentation/MicroTxn#WebPurchasing.
Upon receiving the callback, the title should proceed to the ConfirmPurchase call, shown in the Last Step:
Confirm the Purchase section.
PayPal
With PayPal, the PayForPurchase call is practically the same as with Steam.

PlayFabClientAPI.PayForPurchase(new PayForPurchaseRequest() {
OrderId = "1234567890ABCDEF",
ProviderName = "PayPal",
Currency = "RM"
}, result => {
// Handle success
}, error => {
// Handle error
});

However, in this case there is no convenient client application that sends the payment request to the player.
With PayPal, you need to present the player with the PayPal interface, asking them to verify that they agree to
the purchase. Behind the scenes, this process uses PayPal Express Checkouts, though, because we’re taking care
of all the details.
All you need to do is present the user with the Payment Confirmation page, which is returned to you as the
PurchaseConfirmationPageURL .
{
"code": 200,
"status": "OK",
"data": {
"OrderId": "1234567890ABCDEF",
"Status": "Init",
"PurchaseCurrency": "RM",
"PurchasePrice": 999,
"PurchaseConfirmationPageURL": "https://...",
"CreditApplied": 0
}
}

In this case, once the browser window has been dismissed, that should indicate that it is time to move to
confirming the purchase in PlayFab.

Last step: confirm the purchase


The final part of the process is for PlayFab to complete the purchase process, adding the purchased items (if
any) to the player’s inventory.
In the case of some providers, at this stage the title already knows if the purchase was completed successfully.
In any case, a call to the Client API method ConfirmPurchase will only add the items to the player inventory if the
payment was made, and they haven’t already been added.

PlayFabClientAPI.ConfirmPurchase(new ConfirmPurchaseRequest() {
OrderId = "1234567890ABCDEF"
}, result => {
// Handle success
}, error => {
// Handle error
});

At this point, if the order has been completed successfully, we iterate through the items in the cart that you set
up with the call to the Client API StartPurchase .
This adds the items to the player's inventory and returns the information about the items purchased to the title.

{
"code": 200,
"status": "OK",
"data": {
"OrderId": "1234567890ABCDEF",
"Status": "Succeeded",
"PurchaseDate": "2016-07-19T09:04:28Z",
"Items": [{
"ItemId": "BigBagOfGold",
"ItemInstanceId": "ABCDEF1234567890",
"CatalogVersion": "IAP1_0",
"DisplayName": "A hefty sack of gold",
"UnitCurrency": "RM",
"UnitPrice": 999
}]
}
}

Transaction states
Behind the scenes, there are a number of state changes the order goes through. The complete list is provided
below, though it should be noted that depending on the specific provider process, some of these states will
never show up in the results of any of the three purchase process API calls, and are included here for
completeness.
CreateCar t - While the order object itself is not returned in the response to the Client API StartPurchase
, it has been created at that point. At this stage, the items and prices are stored in the object, but it has not
been submitted to any payment provider.
Init - As shown above, this is the status returned when the order has been submitted to the payment
provider, but has not yet been authorized by the player.
Approved - This occurs briefly, after the player has approved the payment, but before PlayFab has
completed the process of placing the items in the player inventory. It is only included in this list for
completeness, as titles should never see an order with this status.
Succeeded - This indicates that the order has been completed successfully. The player has approved the
payment, and all inventory items have been added to that player's inventory.
FailedByProvider - If for any reason the provider rejects the payment (which includes the player
declining the payment), the order is considered failed by the provider.
DisputePending - The payment provider has notified PlayFab of a dispute on the payment that is
unresolved.
RefundPending - A payment provider has notified PlayFab that a refund request has been issued. At this
stage, the refund has not actually occurred.
Refunded - The order has been refunded. Most (if not all), payment providers also provide this
information directly to the developer. The developer will need to decide how to manage this status, which
can vary depending on a number of factors, such as whether the items are consumable goods (which
may already have been consumed).
RefundFailed - A refund was requested, but was rejected by the payment provider. PlayFab will not be
able to provide any additional information on this - so if more details are needed, the developer should
contact the payment provider directly.
ChargedBack - This status varies by payment provider, and can indicate that an order is in dispute or has
been charged back. Again, for more information on the specifics of the order, the payment provider
should be contacted.
FailedByPlayFab - This status indicates that an unexpected failure occurred in the payment process. On
seeing this status response, the title should retry the previous payment API call. If this status persists, you
are advised to post this issue on our support forums and provide all the details concerning the issue (title
ID, PlayFab ID, order ID).

Accepting Payments with Xsolla


For Xsolla, the process is quite different, and does not use the code flow above as you'll be using the Xsolla
payment flow, as described here: https://developers.xsolla.com/.
First, you'll need to have a merchant ID, project ID, and merchant API key from Xsolla in order to configure your
title to use their payment service.
To get started, use the link in the Add-ons Marketplace's Xsolla page to sign up for an Xsolla account.
Once you have that configuration page set up, your next step will be to create the catalog of goods in the
Xsolla service.
When doing this, verify that the item_code for each item in Xsolla matches an item ID in your PlayFab
catalog, as those are the identifiers we'll be using to complete your purchase and add the correct items to
the player inventory securely.
To set up your list of virtual items in the Xsolla catalog, please refer to their documentation, which we
provided earlier in our instructions.
Initiating the purchase (Xsolla)
Once you're ready to make a purchase, you'll use the GetPaymentToken API call to request a token from the Xsolla
service, by specifying it as the TokenProvider .

PlayFabClientAPI.GetPaymentToken(new GetPaymentTokenRequest() {
TokenProvider = "xsolla"
}, result => {
// Handle success
}, error => {
// Handle error
});

The call will return a ProviderToken , which is the Xsolla token you'll need in the next step, and a PlayFab
OrderId . Behind the scenes, this call initiates the transaction with Xsolla.

{
"code": 200,
"status": "OK",
"data": {
"ProviderToken": "1234567890ABCDEF",
"OrderId": "1234567890ABCDEF"
}
}

Completing the purchase (Xsolla)


Next, the client needs to pass the token to Xsolla to begin the payment process. You can pass that token to Xsolla
using one of the following URLs:
Sandbox payments :

https://sandbox-secure.xsolla.com/paystation3/?access_token=[TOKEN]

Live payments :

https://secure.xsolla.com/paystation3/?access_token=[TOKEN]

Once you have performed that, you'll complete the purchase in the Xsolla interface.
Again, you'll need to refer to the Xsolla documentation found in the link we provided earlier in this instruction
for any questions on using their interface.
Once that is done, there's no further need for you to take any action. Xsolla and PlayFab will exchange webhook
calls, and PlayFab will fulfill the purchase by putting the purchased items into the player inventory and posting
the appropriate events to PlayStream.
You can check the transaction status (see the full list above) by polling the Client API GetPurchase .
In most cases, this process should not take more than 2-3 seconds to complete.
PlayFabClientAPI.GetPurchase(new GetPurchaseRequest()
{
OrderId = "1234567890ABCDEF"
}, result =>
{
// Handle success
}, error =>
{
// Handle error
});

{
"code": 200,
"status": "OK",
"data": {
"OrderId": "1234567890ABCDEF",
"PaymentProvider": "Xsolla",
"TransactionStatus": "Succeeded",
"PurchaseDate": "2017-06-07T00:00:00Z"
}
}

Final notes
One thing to be aware of is that payments can take a long time to complete with some providers.
If you find that the status of the purchase in the response from a call to the Client API ConfirmPurchase is still
Init , you should wait before re-querying. The best practice here is to store the OrderId at the start of the
process, and then use an exponential back-off when querying for the result.
So if the status is Init, wait one minute before re-trying the call to the Client API ConfirmPurchase , then wait two
minutes, then four, eight, etc., until you hit some max value. Including a check for completed transactions
option would then provide a way for the user to reset that timer.
Finally, it’s worth noting that you can use sandbox mode for testing purchases with some payment providers.
To do so, check the Use sandbox purchase testing option from your Title’s Add-on tab in the PlayFab Game
Manager.
PlayFab items
5/24/2022 • 2 minutes to read • Edit Online

Items and inventories are common mechanisms that you can use to add customization and depth to your game.
Defining and tracking items in PlayFab gives you top-notch analytics and LiveOps support for your in-game
catalog.

Key concepts
Catalog - Catalogs offer an easy way to manage your game's virtual items. They are listings of every item
available in your game.
Catalog Items – PlayFab Items can represent just about any type of virtual goods that you might use, from
Durables to Bundles to Locked containers.
Player Inventor y - All player accounts have an inventory. The inventory contains all of the owned Item
Instances as well as the item history to-date.
Vir tual Currency - PlayFab offers up to 10 virtual currencies per title. Currencies can be used to purchase
Items from the Catalog or a Store, represent soft currency converted from In App Purchases, or be used as a
mechanic to drive gameplay.
PlayFab provides a large interactive playing field for interaction with items and inventory, and the Item definition
in the Catalog allows for quite a bit of customization. However, most common interactions are through just a
few key APIs:
PurchaseItem - Buys a single catalog item with virtual currency, subtracting the currency and adding an Item
Instance into the Player/Character Inventory.
GetCharacterInventory and GetUserInventory – These APIs retrieve the specified Character or the player’s
current Inventory of virtual goods.
Items quickstart
5/24/2022 • 3 minutes to read • Edit Online

The Items quickstart gives you the building blocks of your in-game economics: virtual currency, catalogs, items,
and purchases.
In this quickstart, you will:
Set up a virtual currency for your game.
Give virtual currency to a player.
Add an item to your in-game catalog.
Use PlayFab APIs to purchase an item from the catalog using virtual currency.
Use information in the Game Manager to confirm that the purchase was successful.

Setting up a virtual currency


PlayFab supports a robust game economy with multiple currencies and items.
To access these features and create a virtual currency:
1. Open Game Manager and select Economy on the left side bar.
2. Select the Currency tab, and select New Currency . (This opens the New Currency screen shown
below).
3. To create your virtual currency, edit these fields:
Set Currency code (2 uppercase characters) to GD .
Set Display name to Gold .
4. Select SAVE CURRENCY .

Giving virtual currency to a player


You can give players virtual currency directly. As an example, let's add money to a player using the Game
Manager:
1. Select Players on the left side bar, then select the ID of a player.
2. Go to the player's Vir tual Currency tab.
3. Choose the GD currency. (This opens the Modify Vir tual Currency screen shown below).
4. Change the Amount to 100 .
5. Select SAVE VIRTUAL CURRENCY .

TIP
It can be dangerous to give clients the ability to call the AddUserVirtualCurrency API. For information about setting
restrictions on specific APIs, see API access policy.

Now the player has 100 gold. What can they do with it? Buy an item!

Adding an item to your in-game catalog


No sense having money if you can't spend it! Let's create a catalog, (which is a collection of items).
You can create catalogs that correspond to the platforms on which you're releasing your game, or major version
numbers - whatever you like.

TIP
We don't recommend creating multiple catalogs to differentiate types of items. You can filter items more effectively using
classes, tags, and stores.

To make a catalog with an item:


1. Select Economy on the left side bar and select the Catalogs tab.
2. Select the New Catalog button and enter main as the Catalog version . An item with the ID of One is
added automatically.
3. Select One . (This opens the Edit Catalog Item screen shown below). Edit these fields:
Set Item ID to apple .
Set Display name to apple .
Set Description to Perfectly normal apple .
At the bottom of the form is the PRICES section, where you define how much an item costs in your game's
virtual currency.
1. Set the apple's price in gold (GD ) to 5 .
2. Select SAVE ITEM .

Purchasing an item using virtual currency


Let's use the PlayFab APIs to make a purchase in your game.
1. Log in as the player that was assigned 100 gold in virtual currency (as described in [Giving virtual
currency to a player].
2. Call GetCatalogItems with the following parameter in the request:
CatalogVersion = "main"
3. Verify that the Catalog in the result contains an apple with a GD price of 5 .
4. Purchase the apple by calling PurchaseItem with these parameter values in the request:
CatalogVersion = "main"
ItemId = "apple"
VirtualCurrency = "GD"
Price = 5
5. Finally, call GetUserInventory and take a look at the result of that method. In the array of items in the
player's inventory, you should see an apple!

Confirming that the purchase was successful


To confirm the purchase in Game Manager:
1. Select Players from the left side bar to open the Players tab.
2. Select the ID of the player that purchased the item.
Check the following:
Open the PlayStream tab. You should see a Player virtual currency item purchased event.
Open the Inventor y tab. The inventory should now contain an apple. You can also use features on the
Inventor y tab to revoke the item, or grant the player more apples.
Open the Vir tual Currency tab. The player should only have 95 gold left.
Items Tutorials
5/24/2022 • 2 minutes to read • Edit Online

These tutorials describe the items that are part of the economy of your game.
Catalogs
Drop Tables
Timed Consumables
Catalogs
5/24/2022 • 7 minutes to read • Edit Online

This tutorial describes the Catalogs tab in the Economy section in Game Manager . Catalogs are used to
define items that the player can purchase or that you can award to a player.

What is a catalog?
Many games offer the player items for purchase such as a shield, a level-unlock, or a power-up. These items are
specified in a catalog in units of either virtual currency or real money. Catalogs offer an easy way to manage
your game's virtual items. They are listings of every item available in your game.
However, before a player can purchase an item from a catalog, you must first create the items that you want to
populate it.
PlayFab’s Player Item Management (Server) and Player Item Management (Client) APIs support many strategies
for item purchasing, including the following:
Simple real money or virtual currency purchases of items.
Triggered item grants based on buying another item.
Locked (with a potentially purchasable key) and unlocked boxes.
Random result tables.
Non-purchasable items that are granted based on events within a game.

NOTE
In catalogs, the currency type of RM is reserved for real money , which is in cents USD. $1.99 is represented as RM 199 .

Field reference
This section describes each field in the Catalogs section of the Economy area in Game Manager .
When you first create a title, you have no catalogs. You won't see any fields in the Catalogs section until you
create a catalog by selecting the NEW CATALOG button.
Once a catalog is created, you will see the following tabs in the Catalogs section:
Items - Things that have a value in virtual currency or real money that can be purchased or awarded. See
PlayFab items for more information.
Bundles - Collections of items and virtual currency that unpack into a player's inventory when granted.
Containers - Collections of items and virtual currency that remain as an item in the player's inventory until
opened.
Drop Tables - Collections of items and virtual currency you can use to reward players.
Stores - Stores serve a subset of catalog items. These items can be offered at alternative prices to those set
in the catalog. See PlayFab Stores for more information.
New Catalog fields
When you select NEW CATALOG from the main Catalogs tab, you will see the following page:
The New Catalog page (shown above) contains these fields:
Catalog version A required field. This is the name of your catalog that is shown in the Catalogs tab.
Make primar y catalog Indicates whether this is the primary catalog for your game.
New Catalog Item fields
When you select a Catalog and choose NEW ITEM , you will see the following page:

The New Catalog Item page (shown above) contains these fields:
PROPERTIES
Item ID : This required field is the unique identifier for the item within the Catalog. The item ID
must be unique within the Catalog, but you can have multiple catalog versions containing items
with the same item ID.
Item Class : This optional field is an identifier you can use to help manage your catalog items.
Tags : This optional field contains tags that you can use to organize your catalog items. Like the
field name implies, the tags are comma-delimited text strings.
Item image URI : This optional field allows you to provide a URI to an image of the item.
OPTIONS
Is stackable : Marking an item as Stackable allows only one item of this type in the inventory and
increments the quantity count of the item.
Is tradable : Indicates whether the item is tradeable via the trade API calls.
Is a token for character creation : Indicates whether the item is involved in character creation.
PRICES
Currency : Specifies the currency used for the item's cost. Real money (RM) is always available as
it's built into PlayFab.
Amount : This field is required when a currency is selected. It indicates the units of currency for the
item's cost.
DISPL AYED TO PL AYERS
Display Name : This optional field is the name displayed for the catalog item. One common usage
is when you want to offer the item in your in-game store. Display names do not need to be unique.
Description : This optional field is the description for the catalog Item. One common usage is
when you want to offer the item in your in-game store.
LIMITED EDITION
Is limited edition : Indicates whether there is a limited supply of this item.
CONSUMABLE Indicates whether the item is Durable or Consumable .
CONVERT TO : Allows you to convert the item to a bundle or container when it is saved.
CUSTOM DATA This optional field allows you to enter attributes for the item as Key Value Pairs (KVPs).
Only the key is required for each attribute. The KVPs can be entered as a string in the text box, or if EDIT
AS KEY/VALUE PAIRS is selected, entered in the following fields:
Key : A required field. The index to the Attribute Value .
Value : This optional field is the value of the attribute. If this is not set, the value is null.
New Catalog Bundle fields
When you select a Catalog , open the Bundles tab, and choose NEW BUNDLE , you will open the New
Catalog Bundle page.
This page contains all of the fields in the New Catalog Item page, plus this field:
BUNDLE CONTENTS :
ADD TO BUNDLE Displays a list of all the items, currencies, and drop tables in the catalog and allows
you to select which ones to add to the bundle.
New Catalog Container fields
When you select a Catalog , open the Containers tab, and choose NEW CONTAINER , you will open the New
Catalog Container page.
This page contains all of the fields in the New Catalog Item page, plus this field:
CONTAINER CONTENTS :
ADD TO CONTAINER Displays a list of all the items, currencies, and drop tables in the catalog and
allows you to select which ones to add to the container.
New Drop Table fields
When you select a Catalog , open the Drop tables tab, and choose NEW DROP TABLE , you will see the
following page:

The New Catalog Drop Table page contains these fields:


DROP TABLE ID :
Table Id : This required field is the unique identifier for the drop table within the catalog. The value of
Table Id must be unique within the catalog, but you can have multiple catalog versions containing
drop tables with the same Table Id .
TABLE CONTENTS :
ADD TO DROP TABLE Displays a list of all the items and drop tables in the catalog and allows you to
select which ones to add to the drop table.
New Store fields
When you select a Catalog , open the Stores tab, and choose NEW STORE , you will see the following page:
The New Store page contains these fields:
STORE NAME :
Store Id : This required field is the unique identifier for the store within the catalog. The value of
Store Id must be unique within the catalog, but you can have multiple catalog versions containing
stores with the same Store Id .
Store name This optional field is the name displayed for the store. Display names do not need to
be unique.
Description : This optional field is the description for the store.
Custom data This optional field allows you to enter attributes for the store as Key Value Pairs
(KVPs). Only the key is required for each attribute. The KVPs are entered in the text box as JSON.
Selecting the JSON label above the box provides a format for entry.
STORE CONTENTS :
ADD TO STORE Displays a list of all the items in the catalog and allows you to select which ones to
add to the store.
SEGMENT OVERRIDES : These optional fields allow you to set which player segments will be able to use
your store.

NOTE
For detailed information on creating and using stores in your game, see our Stores quickstart, and Stores tutorials.

Example of Catalog creation


To create a Catalog :
1. Open Game Manager and select Economy on the left side bar.
2. Select the Catalogs tab.
3. Select the NEW CATALOG button.
4. Enter a Catalog version (like My Catalog).
An item with the ID of One is added automatically.
5. Select One . (This opens the Edit Catalog Item page which has the same fields as the New Catalog
Item page described above).
Edit or add some properties, such as:
Item ID (e.g. shield_level_5 ).
Display name (e.g. Level 5 Shield ).
Description (e.g. Strong defense against projectile attacks ).
6. Set a price by selecting a currency and amount, for example:
Set the Currency to Gold , (See Currencies for more information on this.)
Set the Amount to 250 ).
7. Select SAVE ITEM .
8. This returns you to the Items page for your catalog. To add more items, select NEW ITEM and repeat
steps 5 – 7.

Uploading a catalog
To upload a JSON file to create a catalog in Game Manager, perform the following steps:
Select your Game in Game Manager .
Select Economy .
Select Catalogs .
Select UPLOAD JSON .
Select your JSON file and choose UPLOAD FILE .

NOTE
You can also save or upload catalogs as JSON files using the Admin APIs GetCatalogItems and SetCatalogItems.
Drop tables
5/24/2022 • 6 minutes to read • Edit Online

This tutorial shows you the steps for creating drop tables using the PlayFab Game Manager.
Drop tables allow you to randomly generate inventory items, and sequential drop tables can provide some
randomness to player rewards.

Requirements
We assume that you are already familiar with Catalogs, Inventory, and the PlayFab Game Manager.
You must have a primary catalog - which contains standard, non-bundle/non-container items.
You must have defined at least one virtual currency which you will use as a "free" in-game currency.
You may use your own set of items, but our goal is to create an overlapping categorization of items.
As an example, we'll use the following table of items:

A C C ESSO RY A RM O R SW O RD

Common Common Accessory Common Armor Common Sword

Uncommon Uncommon Accessory Uncommon Armor Uncommon Sword

Rare Rare Accessory Rare Armor Rare Sword

Legendar y Legendary Accessory Legendary Armor Legendary Sword

Once you have set up a similar set of items to work with in your catalog, we're ready to build the drop tables.

Building drop tables


In Game Manager:
1. Navigate to your Title .
2. Select Economy from the menu on the left.
3. Go to the Catalogs tab and choose your primary catalog.
4. Select Drop Tables .
Your screen should be similar to this example.
Begin building Drop Tables based on each of your item descriptors. Our first categorization is Equipment
Type , so we'll create a new Drop Table called Accessories .
1. Select the New Drop Table button.
2. Set the Table Id to Accessories .
3. Select ADD TO DROP TABLE . The Pick multiple items pop-up will appear.
4. Add these items by selecting the Add button next to their ID :
Common Accessor y
Uncommon Accessor y
Rare Accessor y
Legendar y Accessor y
5. Select the Close button.
6. Adjust the Weight values for the items according to rarity:
Common : 1000
Uncommon : 100
Rare : 10
Legendar y : 1
The weights indicate how frequently the items should drop in comparison to one another. For the
example shown here, you will drop approximately 1000 Commons for every Legendar y .
7. Select SAVE DROP TABLE .
With Accessories completed, follow the same steps to create drop tables for Armors and Weapons .
Our other categorization is by rarity, so we'll create an alternate set of tables starting with Common
Equipment .
1. Select the New Drop Table button.
2. Set the Table Id to Common Equipment .
3. Select ADD TO DROP TABLE . The Pick multiple items pop-up will appear.
4. Add these items by selecting the Add button next to their ID :
Common Accessor y
Common Armor
Common Sword
5. Select the Close button.
6. Adjust the Weight values for the items according to how the Common Equipment options will be in
that slot:
Common Accessor y : 1
Common Armor : 4
Common Sword : 5
7. Select SAVE DROP TABLE .
Using drop tables
You can access drop tables programmatically using these two PlayFab Server API methods:
1. GetRandomResultTables
2. EvaluateRandomResultTable
Using GetRandomResultTables, you can read the raw drop table data that we've just entered into Game Manager.

NOTE
GetRandomResultTables does not roll random values or award results. The API lets you read the data and parse the
information however you see fit.

Option 1

public void ReadDropTableData() {


PlayFabServerAPI.GetRandomResultTables(new GetRandomResultTablesRequest() {
TableIDs = new List<string> { "Accessories", "Common Equipment" }
}, result => {
Debug.Log("Completed getting drop tables");
}, error => {
Debug.LogError(error.GenerateErrorReport());
});
}

The result handler will receive the structure information for the drop table that we created, formatted as a
GetRandomResultTablesResult.
Alternately, you can let PlayFab evaluate the table for you, and give you a single item result using the
EvaluateRandomResultTable API. Doing so returns the itemId that can be used to generate a single item, rolled
according to the weights provided.
You can then make a second call which creates the item and gives it to the player.
Option 2

public void Grant(string playFabId, string tableId) {


// First, roll a random number and evaluate the drop table
PlayFabServerAPI.EvaluateRandomResultTable(new EvaluateRandomResultTableRequest()
{
TableId = tableId
}, result => OnRandomResultTableResponse(result, playFabId), OnError);
}

public void OnRandomResultTableResponse(EvaluateRandomResultTableResult tableResult, string playFabId) {


// Second, take the result and grant it to the player
PlayFabServerAPI.GrantItemsToUser(new GrantItemsToUserRequest {
PlayFabId = playFabId,
ItemIds = new List<string> { tableResult.ResultItemId }
}, result =>
{
// Handle Result
}, OnError);
}

public void OnError(PlayFabError error) {


Debug.LogError(error.GenerateErrorReport());
}

To summarize:
Option 1 - Allows you to load the data once, cache it, and perform the roll yourself on your own game server.
This has lower latency due to fewer calls to PlayFab, and allows you to customize the rolls based on game-
specific logic.
Option 2 - Lets PlayFab do more of the work, but remember - multiple API calls means higher latency.

Advanced drop table usage (setting up a loot crate)


Drop tables can be linked from bundles and containers. Bundles are a great option for virtual currency stores,
where a single purchase yields a stack of random items.
For example, let's say we have an 11 Item bundle with specific drop rules. In this case, it is a customer-facing
selling point that we will guarantee one legendary item. We'll also restrict it, so that the player can't get too
lucky, and receive 11 legendaries .

New Drop Table


Let's build a drop table that can literally drop anything - in fact, we'll actually call it Anything .
When creating this drop table, give it other drop tables as its options (on the Pick multiple items pop-up,
select the Drop Tables tab to add other drop tables), and assign them appropriate weights.
Adding a bundle
At this point, we're done with drop tables and we're going add a Bundle .
1. Select Economy from the menu on the left.
2. Go to the Catalogs tab and choose your primary catalog.
3. Select Bundles and choose New Bundle .
4. Set the Item Id to 11-Item Drop , select Consumable and choose By time 15 Seconds .
5. Select ADD TO BUNDLE .
6. In the Pick multiple items pop-up, select the Drop tables tab.
7. Add the drop tables by selecting the Add button next to their ID .
8. Set the Quantity fields to the values shown in the image below.
9. Select SAVE BUNDLE .
The Bundle that we've created for this example uses several features:
All items of any kind must have an Item ID .
A Bundle counts as its own Item, and its contents are delivered at the same time it is granted. For this
reason, we're making the Bundle itself consumable, and it expires 15 seconds after delivery.
We add different Drop tables in different quantities to ensure that 11 Items are delivered, but different
items roll on different tables.
First, we guarantee at least 1 legendar y item , so the first slot will roll on Legendar y Equipment .
The next 3 slots roll on Anything , which can roll additional Legendaries , or roll less desirable,
common equipment. These rolls will define a good roll vs. a bad one, as these 3 items can vary widely.
Finally, we fill in the remaining slots with guaranteed Rares and Uncommons , ensuring that an 11
Item roll is not too good or bad.

Conclusion
A drop table generates a single item randomly from a list of potential items and weights. Bundles and containers
can be one of the simplest ways to deliver one or more items to a player using drop tables.
You can manually use a drop table from CloudScript, using one of these Server API methods:
1. GetRandomResultTables
2. EvaluateRandomResultTable
Timed Consumables
5/24/2022 • 5 minutes to read • Edit Online

This tutorial walks you through creating timed consumables using the PlayFab Game Manager. Timed
consumables are items that are configured to auto-consume after a specific time from the initial grant to the
player.

Requirements
We assume that you are already familiar with Catalogs, Inventory, and the PlayFab Game Manager.
You must have a primary catalog.

Create a Stackable Timed Consumable


In this example, let's create a small stamina potion that will boost your player's stamina for five minutes when
granted, and increase the time range by an additional five minutes for each additional item. In Game Manager:
1. Navigate to your Title .
2. Select Economy from the menu on the left.
3. Go to the Catalogs tab and choose your primary catalog - your screen should look similar to this
example:

4. Select New item in the top right corner.


5. Fill out the following fields:

F IEL D N A M E SA M P L E VA L UE DESC RIP T IO N

Item ID Small_Stamina_Potion This required field is the unique


identifier for the item within the
Catalog. The item ID must be
unique within the Catalog, but you
can have multiple catalog versions
containing items with the same item
ID.
F IEL D N A M E SA M P L E VA L UE DESC RIP T IO N

Display Name Small Stamina Potion This optional field is the name
displayed for the catalog item. One
common usage is when you want to
offer the item in your in-game store.
Display names do not need to be
unique.

Consumable Consumable Indicates whether the item is


Durable or Consumable .

By Count 1 This required field (when


Consumable is selected)
determines how much the count of
that item will be decremented when
consumed.

By Time 5 Minutes This optional field (when


Consumable is selected)
determines the amount of time that
will elapse from the moment the
item is granted to the moment it is
consumed.

Time Group Name Small_Stamina_Potion This optional field (when


Consumable is selected) allows
you to join multiple item
consumption times with the same
group name together.

Is Stackable True Marking an item as Stackable


allows only one item of this type in
the inventory and increments the
quantity count of the item.

6. Select Save item .


You will now be able to stack these potions and the remaining time will automatically "stack" as well. For
example, if I grant one small stamina potion to a player at 1:00pm, the item will be consumed at 1:05pm. If I
grant another small stamina potion at 1:02pm, the two items will now be consumed at 1:10pm.
NOTE
If you do not specify a time group name for a stackable timed consumable, the full stack will expire when the original
expiration time was set from the first grant. For example, in the scenario above, if I instead left the time group name
blank, if I grant one small stamina potion to a player at 1:00pm, the item will be consumed at 1:05pm. If I grant another
small stamina potion at 1:02pm, the two items will still be consumed at 1:05pm. If I grant yet another small stamina
potion at 1:04pm, the three items will still be consumed at 1:05pm. But after the stack is consumed, if I grant a small
stamina potion at 1:10pm, the item will now be consumed at 1:15pm.

Create a Non-Stackable Timed Consumable


Let's create a similar example as before, but with a non-stackable item. Let's create a medium stamina potion
that will boost your player's stamina for ten minutes when granted, and increase the time range by an additional
ten minutes for each additional item. In Game Manager:
1. Navigate to your Title .
2. Select Economy from the menu on the left.
3. Go to the Catalogs tab and choose your primary catalog - your screen should look similar to this
example:

4. Select New item in the top right corner.


5. Fill out the following fields:

F IEL D N A M E SA M P L E VA L UE DESC RIP T IO N

Item ID Med_Stamina_Potion This required field is the unique


identifier for the item within the
Catalog. The item ID must be
unique within the Catalog, but you
can have multiple catalog versions
containing items with the same item
ID.
F IEL D N A M E SA M P L E VA L UE DESC RIP T IO N

Display Name Medium Stamina Potion This optional field is the name
displayed for the catalog item. One
common usage is when you want to
offer the item in your in-game store.
Display names do not need to be
unique.

Consumable Consumable Indicates whether the item is


Durable or Consumable .

By Count 1 This required field (when


Consumable is selected)
determines how much the count of
that item will be decremented when
consumed.

By Time 10 Minutes This optional field (when


Consumable is selected)
determines the amount of time that
will elapse from the moment the
item is granted to the moment it is
consumed.

Time Group Name Med_Stamina_Potion This optional field (when


Consumable is selected) allows
you to join multiple item
consumption times with the same
group name together.

Is Stackable False Marking an item as Stackable


allows only one item of this type in
the inventory and increments the
quantity count of the item.

6. Select Save item .


Now every time you grant an additional medium stamina potion, it will create an entirely new instance in the
player's inventory, as the item is not stackable - however, you will still be able to automatically "stack" the
remaining time for those items. For example, if I grant one medium stamina potion to a player at 1:00pm, the
item will be consumed at 1:10pm. If I grant another medium stamina potion at 1:05pm, the two items will now
be consumed at 1:20pm.

NOTE
If you do not specify a time group name for a non-stackable timed consumable, each instance will expire independently of
one another. For example, in the scenario above, if I instead left the time group name blank, if I grant one medium
stamina potion to a player at 1:00pm, the item will be consumed at 1:10pm. If I grant another medium stamina potion at
1:05pm, the first item will still be consumed at 1:10pm, and the second item will be consumed at 1:15pm.

Link Multiple Timed Consumables


Now that you have a Small Potion (stackable) and a Medium Potion (non-stackable), let's link those two timers
together. Let's modify a few fields to allow your player's stamina to get boosted when the small or medium
stamina potions are granted, and increase the time range by an additional five or ten minutes for each small or
medium stamina potion, respectively. In Game Manager:
1. Navigate to your Title .
2. Select Economy from the menu on the left.
3. Go to the Catalogs tab and choose your primary catalog - your screen should look similar to this
example:

4. Select Med_Stamina_Potion in the item list.


5. Change the Time Group Name from Med_Stamina_Potion to Stamina_Potion .
6. Select Save item .
7. Select Small_Stamina_Potion in the item list.
8. Change the Time Group Name from Small_Stamina_Potion to Stamina_Potion .
9. Select Save item .
Now every time you grant an additional small or medium stamina potion, it will automatically "stack" the
remaining time for all items with the same time group name. For example, if I grant one medium stamina potion
to a player at 1:00pm, the item will be consumed at 1:10pm. If I grant a small stamina potion at 1:05pm, the two
items will now be consumed at 1:15pm.
PlayFab Stores
5/24/2022 • 2 minutes to read • Edit Online

Stores are the best way to let players purchase items in your game. You can use the Game Manager to change
the order of items, and adjust prices at any time. Using segments, you can even give special prices to certain
players without touching your game code.

Key concepts
Catalog - Catalogs offer an easy way to manage your game's virtual items. They are listings of every item
that is available in your game.
Catalog Items – PlayFab Items can represent just about any type of virtual good that you might use, from
durables, to bundles to locked containers.
Player Inventor y - All player accounts have an inventory. The inventory contains all of the owned Item
Instances, as well as the item history to-date.
Character Inventor y - Similar to player inventory, except stored at a per-character level.
Vir tual Currency - PlayFab offers up to 10 virtual currencies per title. Currencies can be used to purchase
Items from the Catalog or a Store, represent soft currency converted from In App Purchases, or be used as a
mechanic to drive gameplay.
Segments - Provides subsets of players grouped by their event history. For example, the "Frequent Players"
segment is comprised of players that have logged in more than 100 times.
Stores - Stores serve a subset of Catalog Items. These items can be offered at alternative prices when
compared to those set on the corresponding Catalog Items.
Stores contains an array of references to items defined in your catalog, along with the prices for the item, in both
real world and virtual currencies. Store prices act as an override to any prices defined in the catalog.
In this way, the base definitions of the items may be defined in the catalog, with all associated properties, while
the pricing can be set for each store as needed. This allows for subsets of goods to be defined for different
purposes, and can be used to:
Easily organize your in-game storefront.
Create and organize sales.
Make the Items available for a set time period.
Appropriate certain Catalog Items to specific in-game vendors.
Override the Base Catalog prices for certain player Segments.
Stores are built on top of your game's Virtual Catalogs and Currencies. Think of your primary Catalog as a
definition of all the items in your game, and Stores as an override.
Although you can use the Title Data Management APIs SetStoreItems and UpdateStoreItems to control them
programmatically, Stores are normally set up in Game Manager.
Stores quickstart
5/24/2022 • 4 minutes to read • Edit Online

Stores are the best way to let players purchase items in your game.
As shown in the Items quickstart, PlayFab supports buying items out of a catalog, but that's not how most
games structure their purchases. Whether you're making an idle clicker, an RPG, an FPS, or an endless runner,
you probably have vendors in your game where players can buy weapons, armor, or running shoes.
Our solution for this is Stores, a subset of your catalog with prices you can override.
In this stores quickstart, you will:
Add items to a catalog with regular prices.
Create a store that contains the same items with discounted prices.
Use PlayFab APIs to purchase an item from the store.
Use information in the Game Manager to confirm that the item was purchased at the discounted store price.

Adding items to a catalog


First, let's add some Items to sell in your catalog:
1. Open Game Manager and select Economy on the left side bar.
2. Select the Catalogs tab, and open your main catalog.
3. Select New Item a few times, and create some items:
apricot with a GD price of 4 .
pear with a GD price of 3 .
grape with no GD price (don't select any prices).

TIP
You don't have to assign a virtual currency price to items in a catalog for them to appear in a store.

In the following example, an item called apricot is added to the main catalog with a GD price of 4 .
Creating a store
You should now have a few items with prices in your catalog. Let's create a store to sell them to a player.
1. Open your main catalog and select Stores .
2. Select New store .
3. Set the Store Id and Store name to fruits (as shown in the following example).

4. Select ADD TO STORE .


A pop-up screen - like the one shown below - will display all the items, bundles, and containers in the
current catalog.
5. Add a few items to your store by selecting the Add button next to the item.
Setting the store price for an item
You should now see your items listed in the STORE CONTENTS , but they're not valid until they have at least
one price.
The little static number (for example, < 4 ) next to the price text box is the original catalog price. You only have to
enter a price for one box in each row, but you can enter as many prices as you want.
If you don't enter any price for an item, it will be removed from the store.
If a store item doesn't have a price in a currency, it can't be bought using that currency.
Store prices can be higher than catalog prices, and zero is a valid price for an item.

TIP
You can drag-and-drop the rows in the store contents to rearrange the order of the items.

1. Add some GD prices to your items, but make them lower than the catalog prices:
Apricot: 3 .
Pear : 2 .
Grape: 1 .
2. Select SAVE STORE when you're done.
In the following example, an item called apricot with a catalog price of 4 GD is given a store price of 3 GD .
Purchasing an item from the store
Now that you have a store, let's use the PlayFab APIs to buy an item from the store in your game.
1. Get your store by calling GetStoreItems with these parameters in the request:
CatalogVersion = "main"
StoreId = "fruits"
2. The Store field in GetStoreItemsResult should contain a list of your store items and their prices.
3. Call PurchaseItem with values in the request that specify the currency and store price of the item you
want to buy.
CatalogVersion = "main"
StoreId = "fruits"
ItemId = "pear"
VirtualCurrency = "GD"
Price = 2

TIP
If you don't specify the StoreId when calling PurchaseItem, the purchase is attempted against the catalog price.

Confirming the purchase price


Open Game Manager, and confirm that the purchase was made at the store price of 2 GD.
1. Select Players from the left side bar to open the Players tab.
2. Select the ID of the player that purchased the item.
3. Check the following information for the player:
Open the Inventor y tab. The inventory should now contain a pear .
Open the Vir tual Currency tab. Check the virtual currency Amount to verify that the player only
spent 2 GD.
Open the PlayStream tab. You will see events showing the purchase flow from the store. These
should include a Player virtual currency item purchased event, and a Player virtual currency balance
changed event showing that the virtual currency balance changed by 2 GD.
TIP
You can use the Game Manager to change the order of items in your store and adjust prices at any time.

Next steps
Now that you've learned how to create and utilize stores in your game, you're ready to explore some more
advanced uses of stores.
For example, by using segments in conjunction with stores, you can give special prices to certain players without
touching your game code.
Custom stores for player segments
Best practices for store segmentation
Also, by combining stores and segments with A/B testing, you can produce several versions of a store available
to different A/B testing groups (buckets).
A/B testing with stores and test buckets
Stores tutorials
5/24/2022 • 2 minutes to read • Edit Online

These tutorials show you how to use stores.


Best Practices for Store segmentation
Custom Stores for Player Segments
Stores and Sales
Best practices for store segmentation
5/24/2022 • 2 minutes to read • Edit Online

Store segmentation is public information.


There are many ways for players to gain information about alternate stores.
Players naturally transition between segments, and see those changes when they transition.
Players discuss content on forums, community sites, wikis, etc.
In the PlayFab API, store information is public, unless you disable those APIs with our API Access
Policy.
You should assume that players will be aware of other stores and their details.
Provide varying content, not varying pricing.
Players will feel cheated if:
Prices go up or down when they transition segments.
Prices described on wikis are different than their own.
The only exception to the pricing rule would be first time purchases.
You must secure the Client API methods with our API Access Policy to prevent multiple
purchases, or make repurchasing less meaningful through game design.
Content should be relevant to the segment.
Whales are willing to spend large amounts of real money, and are therefore likely to buy more
expensive bundles, if the value is worthwhile.
First time buyers may be given an option which is a particularly good deal, but can only be (usefully)
obtained once.
End game players may only be interested in a specific subset of items.
Custom stores for player segments
5/24/2022 • 2 minutes to read • Edit Online

In our Stores and Sales tutorial, we demonstrate how to set up a store and make a few items available to a
player at special or alternate prices.
In our Player segmentation quickstart, we provide an example of how to group your players into segments,
based on player information or behavior.
This tutorial describes how to combine these features, and produce alternate stores available only to players
from defined player segments.
1. Let's begin with some example segments. In the screen shot shown below, we have provided some segments
that are segmented-store-testing friendly.

2. Next, we'll reuse the Equipment Store created in the Stores and Sales tutorial, and add player segmentation.
To do this, you must create each store separately, and give it an identifiable name. Each store should have
content that is customized for that segment.

TIP
Using the DUPLICATE feature on the Stores screen, you can duplicate stores quickly, and then modify the Store Id ,
Store name , and other parameters to make the new store unique.

The following screen shot shows our customized stores.


3. Finally, edit the Equipment Store , and fill in the SEGMENT OVERRIDES section at the bottom (this section
is only visible if there are defined player segments).
Best Practices for store segmentation
Store segmentation is public information:
There are many ways for players to gain information about alternate stores.
Players naturally transition between segments, and they'll see those changes when they transition.
Players discuss content on forums, community sites, wikis, etc.
In the PlayFab API, store information is public unless you disable those APIs with our API Access Policy.
You should assume that players will be aware of other stores and their details.
Provide varying content, not varying pricing:
Players will feel cheated if:
Prices go up or down when they transition segments.
Prices described on wikis are different than their own.
The only exception to the pricing rule would be first time purchases:
You must secure the client API methods with our API Access Policy to prevent multiple
purchases, or make repurchasing less meaningful through game design.
Content should be relevant to the segment:
Whales are willing to spend large amounts of real money - and are therefore likely to buy more
expensive bundles - if the value is worthwhile.
First time buyers may be given an option which is a particularly good deal, but can only be (usefully)
obtained once.
End game players may only be interested in a specific subset of items.
Stores and sales
5/24/2022 • 8 minutes to read • Edit Online

In PlayFab, Stores are built upon Catalogs and Currencies. Your primary catalog should define all of the items in
your game and assign them prices in the currencies that you've created.
Stores should define subsets of the items in your catalog, and make them available for purchase at specific
prices that can be different than the catalog prices.
A store allows you to single out a specific set of items, and make them available at specific prices for a set time
period.
This tutorial illustrates the best practices for defining stores based on virtual currency and real money.

Requirements
Familiarity with the PlayFab Game Manager.
You must have defined one or more Virtual Currencies. The latter example in this tutorial uses:
SS (Silver Shekels )
GS (Gold Shekels ).
You must have a primary catalog with one or more items defined.
The first example uses multiple item/bundles, similar to the ones described in the Drop Tables tutorial.
The second example in this tutorial uses small, medium, and large health potions.
Best practice
Catalog prices should be fixed long-term - they define the real price of an item.
Stores should be temporary, being added and removed according to your LiveOps strategies.

NOTE
Expect to get most of your revenue by cycling stores, and transitioning items in and out of active stores.

General information about stores and catalog pricing


Please note the following information about stores and currencies:
Pricing : The prices defined in the catalog should be defined as the regular price of an item. Stores allow
you to define a temporary sale price for an item, utilizing the common retail tactic. Alternately, stores can
provide a temporary price for an item that is not normally available for sale at all.
Zero Cost : If the cost of an item in a particular currency is unset (null ) or zero , it cannot be purchased
using that currency. This is true for both catalogs and stores. This allows you to make items available for
exclusively free currencies, or exclusively premium currencies, by leaving the entries for the other
currencies blank or by resetting them to zero .
Real Money : The RM currency is available in all catalogs and stores. RM is a restricted currency key that
indicates real money transactions only. You should only charge RM for items of significant value, or
bundles/containers which contain premium currency.
Prices are Either/Or : If two prices are defined on an item, the item can be purchased for one or the
other. It is not possible to require two currencies for a single item.

Defining a real money store


In your Game Manager :
Navigate to your Title .
Select Economy from your menu on the left.
On the Catalogs tab, select your primary catalog and select Stores .
Select the New Store button.
In the Drop Tables example, we created an 11-item drop bundle. For this example, we will make 3 similar
bundles available in a real money store.

NOTE
Any item can be sold for real money, but it is a best practice to make only specific valuable items or bundles directly
available.

The screenshot provided below shows a complete new Store , containing three Item Bundles available for Real
Money .
The specifics for completing real money purchases are covered in our advanced tutorial, non-receipt payment
processing.
Best practices for real money stores
How you use real money is largely dependent on the specific design of your game. Direct purchase of in-game
items is valid, but less common.
More typically, your game should allow purchase of a premium virtual currency using real money. You can cycle
multiple stores with different ratios of premium currency to real money.

TIP
The primary takeaway is - make sure your players can always give you money.
Defining a virtual-currency store
Let's get into the gritty details and code for purchasing in-game items with virtual currency.
The initial steps are nearly identical to the preceding example:
Create 3 new items: Small , Medium , and Large Health Potions with a free Currency price, and a
premium Currency price.
Create a new store which puts these items on sale.

Purchasing multiple items in a single purchase


To purchase a single item for virtual currency, use the PurchaseItem method, as described in our Stores
quickstart.
This tutorial, however, covers the more advanced topic of purchasing multiple items in a single purchase.
Your first step in this process should be to get the store, and display it to the user.
void GetVcStore()
{
var primaryCatalogName = "TestCatalog-001"; // In your game, this should just be a constant matching
your primary catalog
var storeId = "Potion Store"; // In your game, this should be a constant for a permanent store, or
retrieved from titleData for a time-sensitive store
var request = new GetStoreItemsRequest
{
CatalogVersion = primaryCatalogName,
StoreId = storeId
};
PlayFabClientAPI.GetStoreItems(request, LogSuccess, LogFailure);
}

The LogSuccess callback in this example receives a GetStoreItemsResult that contains a full description of all the
items in the store, their store prices, and any additional metadata contained in the store itself.
Best practices for displaying stores
Games with stores should call and cache their primary catalog using the GetCatalogItems method. This allows
you to display both the catalog price and the store price, along with a 10% OFF or similar bonus decoration
beside items for sale.

TIP
Players are more likely to buy items on sale, especially if the sale is a limited-time offer.

At this point, it is the responsibility of your GUI code to present the user with the opportunity to select which
items they wish to buy and how many.
Between your game and PlayFab, the remaining steps are several separate API calls, but you can make the
sequence of multiple calls invisible to the player.
Collect all information about the purchase up front, and make the full sequence of calls after all player
input is collected.

void DefinePurchase()
{
var primaryCatalogName = "TestCatalog-001"; // In your game, this should just be a constant matching
your primary catalog
var storeId = "Potion Store"; // At this point in the process, it's just maintaining the same storeId
used above
var request = new StartPurchaseRequest
{
CatalogVersion = primaryCatalogName,
StoreId = storeId,
Items = new List<ItemPurchaseRequest> {
// The presence of these lines are based on the results from GetStoreItems, and user selection
- Yours will be more generic
new ItemPurchaseRequest { ItemId = "Small Health Potion", Quantity = 20,},
new ItemPurchaseRequest { ItemId = "Medium Health Potion", Quantity = 100,},
new ItemPurchaseRequest { ItemId = "Large Health Potion", Quantity = 2,},
}
};
PlayFabClientAPI.StartPurchase(request, result => { Debug.Log("Purchase started: " + result.OrderId); },
LogFailure);
}

During the item selection process, you must allow the user to select which currency they wish to spend for these
items. In this example, all items have costs in SS and GS , which means the user has a choice of which currency
to spend.

NOTE
The result from the StartPurchase API in the code example above, contains a list of PaymentOptions . Each payment
option contains the Currency , Price , and ProviderName that can be used to make the purchase.

Restrictions
Only one virtual currency is allowed in a single purchase. All selected items must be purchasable with a single
currency.
The currency must be specified in the call, which is important when there are multiple possible currencies. The
sequence will fail if there are items in the request which don't have corresponding costs in the selected currency.
The ProviderName must also be specified in the call. For real money purchases, this will be the name of the
provider that is used to fund the purchase. For example, Facebook, PayPal, or Steam. For VC purchases, it will be
a string based on your title ID. The ProviderName can be obtained from the PaymentOptions field of the
StartPurchaseResult as described in the previous Note .

TIP
For VC purchases, the ProviderName for your title is a string constructed from the word "Title" concatenated with the
decimal equivalent of your hexadecimal TitleId . For example, "Title123456".

Best practices for displaying store items


Avoid confusion for your player by ensuring that all items in a store have consistent options.
Real money items should be in a separate store from premium VC items, and again separate from free VC items.
If a single store allows multiple currencies, then all items in that store should consistently use the same set of
multiple currencies. Create as many stores as you need to provide a smooth customer experience.

void DefinePaymentCurrency(string orderId, string currencyKey, string providerName)


{
var request =new PayForPurchaseRequest {
OrderId = orderId, // orderId comes from StartPurchase above
Currency = currencyKey, // User defines which currency they wish to use to pay for this purchase
(all items must have a defined/non-zero cost in this currency)
ProviderName = providerName // providerName comes from the PaymentOptions in the result from
StartPurchase above.
};
PlayFabClientAPI.PayForPurchase(request, LogSuccess, LogFailure);
}

Finally, once the purchase is fully defined, you can complete the process, as shown below.

// Unity/C#
void FinishPurchase(string orderId)
{
var request = new ConfirmPurchaseRequest { OrderId = orderId };
PlayFabClientAPI.ConfirmPurchase(request, LogSuccess, LogFailure);
}

Best practices for handling API failure results


Any single API call can fail for a variety of reasons. Wireless devices such as phones can often have intermittent
connectivity, and any internet call can fail due to random latency.
Each call should check for multiple failure conditions. If the response indicates that the purchase request is
invalid (unable to buy multiple items with a single currency for example) then you should abort (and possibly
re-design your store).
If the response indicates a connectivity failure, you can try again with an exponential back-off delay.

Conclusion
Stores are a great mechanism for encouraging your players to purchase items.
Stores work with any kind of virtual currency. Stores can also work with real money through an alternate set of
API methods.
You can set up a single-item purchase with VC via PurchaseItem.
You can set up a multiple-item purchase with real money or VC via the sequence:
StartPurchase
PayForPurchase
ConfirmPurchase
For more information on real money purchases, consult our advanced tutorial Non-Receipt Payment Processing.
For advanced store usage, see our Custom Stores for Player Segments tutorial.
PlayFab User Generated Content
5/24/2022 • 2 minutes to read • Edit Online

PlayFab User Generated Content (UGC) empowers your players to create, upload, and search for moderated
content. Designed to provide out-of-the box capabilities that normally require custom work and service
expertise to accomplish, our UGC services can enable you to build an engaging creator community around your
title in no time! Watch our UGC Microsoft Game Dev video to learn more.

Key features
UGC provides the following key features:
Easy-to-integrate APIs to allow you to build your own in-game experiences
Moderation built into the publishing pipeline to ensure content is safe and appropriate for your players
Search experiences to allow your UGC catalog to scale and players to quickly find interesting content for
them
Review and reporting capabilities to empower players to keep the quality high

Key concepts
There are a few common terms used throughout the UGC service:
Catalog - Catalogs are a place for you to store and manage your content. There are two main catalogs, the
draft catalog and the public catalog which store draft and published items, respectively
(Published) Items - PlayFab UGC Items are data blobs containing information about a specific item.
Published Items are accessible to other players through the GetItems and Search APIs
Draft Items - Draft Items are accessible to only the item creater and the Title Entity. Draft Items can
become Published Items by calling the PublishDraftItem API
Content - Content are the images and files that are uploaded to Items

Limitations and important considerations


Before playing around with the UGC features and APIs, there are a few limitations and important considerations
you should know about the service:
UGC only supports PlayFab Entities - you will need to use entity-based authentication to utilize UGC.
UGC does not work with the existing PlayFab Economy APIs - it is a separate service built on top of a new
Economy system (still in private preview).

Getting Started
The UGC Quickstart guide walks you through the steps of publishing an item
The Publish your first user generated content tutorial goes over the details of uploading content and
populating URL blobs.
The Search Guide goes over the different ways you can query your public UGC catalog
User-Generated Content (UGC) quickstart
5/24/2022 • 2 minutes to read • Edit Online

The purpose of this guide is to explain how to quickly get started with UGC, using direct service-to-service calls.
We will show you step by step how to connect to the draft UGC content items, publish those items, and then
search and find them.

Get an Entity Token


UGC is designed to work with PlayFab entities, so the first step is to get an entity token using LoginWithCustomID .
As a service call, that looks something like this:

{
"CustomId": "exampleUser",
"CreateAccount": true,
"TitleId": "DC7B"
}

Create a draft UGC item


You create "draft" UGC items by calling the CreateDraftItem API with the "Type":"ugc" parameter. Draft items
are designed to be reviewed and accessed by their creators before being moved to a published state. To create a
draft item you need:
The EntityToken from the previous call in the X-EntityToken header.
The Entity.Id from the previous call in the item's CreatorEntityKey.Id .
The TitleId for the title in the item's sourceId.

This call looks something like the following.

{
"Item": {
"Type": "ugc",
"Title": {
"NEUTRAL": "Neutral Title Test",
"en-GB": "en-gb Title",
"en-US": "en-us Title"
},
"Description": {
"NEUTRAL": "Neutral Description Test",
"en-GB": "en-gb Description",
"en-US": "en-us Description"
},
"startDate": "2018-10-18T20:01:26.1520582Z"
}
}

This will return the created Draft Item with an Id . We'll want to keep track of this Id for later.
"Item": {
"SourceEntity": {
"Id": "1184A",
"Type": "title",
"TypeString": "title"
},
"SourceEntityKey": {
"Id": "1184A",
"Type": "title",
"TypeString": "title"
},
"Id": "44857e2b-c93b-4054-80be-7890028201ff",
"Type": "ugc",
"Title": {
"NEUTRAL": "Neutral Title Test",
"en-GB": "en-gb Title",
"en-US": "en-us Title"
},
...
}

Get draft item IDs for a player


To get draft item IDs for a particular player, the GetEntityDraftItems API can be used. Title entities can call this
API with player ID in the Entity parameter, and the API will return a list of Draft Items for that particular player.
Only Title Entities can pass in an Entity parameter. Player entities can call the API without an Entity
parameter and the API will return a list of draft items created by the calling player.

{
"Count": 2,
"Entity": {
"Id": "C88F55C6A734B1DC",
"Type": "title_player_account",
"TypeString": "title_player_account"
}
}

Publish a UGC item


Once an item is in draft, you can then push it to a published state using PublishDraftItem . Once a UGC item is
published, it's generally searchable and available publicly. You need to use the item Id returned from the
CreateDraftItem response.

{
"Id": "44857e2b-c93b-4054-80be-7890028201ff"
}

Get the published status of a UGC item


Using the item , you can get the status of a publish for an item in your UGC catalog using the
Id
GetItemPublishStatus API.

{
"Id": "44857e2b-c93b-4054-80be-7890028201ff"
}
The possible publish Result values are as follows:
Unknown
Pending
Succeeded
Failed
Canceled

Republishing an item will update the Published Item to match the current Draft Item.

Do a simple search
Once the publish call succeeds, the item can be accessed by all players via the Public Catalog. The SearchItems
API executes a search against published catalog (including UGC items) using the provided parameters and
returns a set of paginated results. The Filter , OrderBy , and Select fields use OData as the query standard.

{
"Search": "Test",
"Count": 2
}
SearchItems
5/24/2022 • 6 minutes to read • Edit Online

The SearchItems API executes a search against the public Catalog using the provided search parameters and
returns a paged list of items.
At its most basic, the Search parameter is a plain-text fuzzy search against the Title , Description , Keywords ,
and Searchable String Display Proper ties fields. However Filter , OrderBy , and Select are OData Query
additions that can be used to alter the search parameters. Search results can be filtered and ordered by any field
in the search document (barring Title and Description).
More information on the OData Query Syntax can be found here
An example SearchItems request:

{
"Search": "Pirates",
"Filter": "Tags/any(t:t eq 'desert') and ContentType eq 'map'",
"OrderBy": "lastModifiedDate asc",
"ContinuationToken": "abc=",
"Count": 2,
"ConfigurationName": "SearchConfigurationA",
"ExpandReferencedItems": false
}

A sample response:

{
"code": 200,
"status": "OK",
"data": {
"Items": [
{
<item metadata>
}
],
"PartialExpandedResults": false,
"ContinuationToken": "MTA="
}
}

Continuation Tokens
The ContinuationToken field that is returned from a search response can be passed into a search request to
paginate through multiple counts of results.

Display Properties
Searches, filters, and orderings can be also done on specific DisplayProperties fields that are configured for
custom search. Titles can configure their custom search and filter properties in the Display Properties Mappings
setting in Game Manager.
When you add a field to DisplayProperties , it will create a new index for you in the database. Only documents
added or updated after index creation will be included. If you need the Display Property to apply to all items you
will need to republish the entire catalog.
DateTime , Double , and Queryable String display properties are quer yable , these properties can be used in
Filter and OrderBy statements.
Searchable String display properties are searchable , these properties will be queried with fuzzy search
against the Search field. Searchable properties cannot be used in Filter and OrderBy statements.
Titles are limited to 5 display properties of each type.

WARNING
Display property mappings are stored as an indexed list of key-value pairs. Deleting existing display property mappings
can shift indexes and break the behavior of all remaining properties. It is suggested to add an additional property rather
than deleting or editing an existing one and you should avoid deleting property mappings unless absolutely necessary

Filter
The Filter parameter allows you to filter the collection of items returned by the search request. The expression
specified with filter is evaluated against each Catalog Item in the results, and only items where the expression
evaluates to true are included.
Filter supports OData logical operators and precedence using parenthesis:
Equal: ‘eq’
Not Equal: ‘ne’
Greater Than: ‘gt’
Greater than or Equal: ‘ge’
Less than: ‘lt’
Less than or Equal: ‘le’
Logical And: ‘and’
Logical Or: ‘or’
Logical Negation ‘not’
Filter does not support arithmetic operators or string functions.
The following are a number of Filter examples:
Filtering by ContentType

"Filter": "ContentType eq 'Sword'"

Filtering with Conjunctions

"Filter": "rating/average gt 1 and rating/average lt 4"

Filtering with null values


OData supports a null type for filtering

"Filter": "rating eq null"

The above request returns all items with no reviews


Filtering by Creator ID
To filter by a specific creator, you should use the syntax title_player_account!<ID>

"Filter": "creatorId eq 'title_player_account!C88F55C6A734B1DC'"

Filtering by Array fields


Filter also supports any() for filtering against arrays. For example:
alternateIds/any(a: a/value eq ‘StoreOfferId’)

"Filter": "tags/any(t: t eq 'featured')"

Filtering with Arrays and null checks


The filter below will check for any items that have a contents field with non-null values

"Filter": "contents/any(content: content ne null)"

NOTE
By default, Search will NOT return contents for items unless specified with a Select statement. If the above query is run
without a `"Select": "contents"`` statement, it will correctly apply the filter but all returned Search results will have empty
content fields

Filtering by Display Properties


Filtering can only be done with quer yable Display Properties

"Filter": "DisplayProperties/DifficultyRating ge 5"

OrderBy
OrderBy is a comma-separated list used to sort search results.
"OrderBy": "rating/average asc"

When using order sorting you can pass a secondary property to break sorting ‘ties’

"OrderBy": "rating/average asc, rating/totalCount desc"

If you don’t pass in a secondary value, catalog items do have an internal ‘score’ attribute that used for breaking
ties, however that scoring is arbitrary and inconsistent (it’s based on the storage order in the underlying
database and is constantly changing as items are added and removed).
OrderBy supports a handful of OData properties for ordering:
asc
desc
If you don't specify a direction, the default is ascending. If there are null values in the field, null values appear
first if the sort is asc and last if the sort is desc . If no OrderBy value is passed, a default id asc value is used.
The following are a number of OrderBy examples:
Sorting by Title
Use the title/<LANG> parameter combined with asc or desc to indicate order preference.

"OrderBy": "title/en-GB asc"

Use NEUTRAL to order by the neutral strings

"OrderBy": "description/NEUTRAL desc"

Sorting by Display Properties


Sorting can only be done with quer yable Display Properties

"OrderBy": "DisplayProperties/DifficultyRating desc"

Select
By Default, Search returns a rich set of item metadata:
Id
Type
AlternateIds
Title (NEUTRAL or Accept-Language locale)
Description (NEUTRAL or Accept-Language locale)
Keywords (NEUTRAL or Accept-Language locale)
ContentType
Images (Thumbnail only)
Tags
CreationDate
LastModifiedDate
CreatorEntityKey ( CreatorId in earlier API versions)
DisplayProperties

Only the neutral strings used in title and description are returned by default. If a Thumbnail image exists, it is
returned by default. Each item is limited to only one image of a "Thumbnail" type.
Using Select additional fields can optionally be returned within the paged search results, including content
metadata (contents), images, StartDate, EndDate and the full set of localized strings in title and description. Note
that if the select field is left empty, the search results will be a subset of the full document metadata, to facilitate
faster load times.
This request would return the default item metadata in addition to the content and images:

"Select": "contents,images"

Selecting title , description , and/or keywords will return the full set of localized string data:

"Select": "title,description,keywords"

Localization
A locale can be passed into the Accept-Language header. This will cause all Title , Description , Keywords fields
to return the locale by default or NEUTRAL if the item doesn't have that localization.

Limits
We are limiting the complexity of search filter queries that can run in any given request. Expensive queries can
be rejected and titles should ensure that they are not attempting overly complicated queries. The following are
examples of queries close to maximum complexity:
contentType eq 'testType' and tags/any(t: t eq 'blue') or tags/any(t: t eq 'green') or tags/any(t: t eq
'violet')
contents/any(c: c/minClientVersion gt '1.2.3' and c/maxClientVersion lt '4.5.6')

High complexity filter queries will throw a 400 error with a message that "The filter provided in the request does
not meet the complexity requirements for source"

Escaping special characters


In order to use any of the special characters as part of the search text, escape the character by prefixing it with a
double backslash ( \\ ). For example, for a wildcard search on https:// , where :// is part of the query string,
you would specify "Search":"https\\:\\/\\/*" . Similarly, an escaped phone number pattern might look like this
\\+1 \\(800\\) 642\\-7676 .

Special characters that require escaping include the following: + - | ! ( ) { } [ ] ^ " ~ ? : \ /


Moderating your user generated content
5/24/2022 • 2 minutes to read • Edit Online

This guide will go through the API calls that can be used to create moderation flows for the content in your
game.

Report an item
Players can report an item by calling the ReportItem API from a client. An item Id or AlernateId must be
provided. Additional optional parameters can be added. These include:
ConcernCategory : A category of concern for the report
Reason : A free text input for the report

Here is a sample request body:

{
"Id": "3f5dd8d4-4ee1-4748-8855-56a8a0277bf9"
"ConcernCategory": "Profanity",
"Reason": "There was swearing in the description."
}

If not specified, ConcernCategory will default to None . The valid ConcernCategory values are as follows:
None
OffensiveContent
ChildExploitation
MalwareOrVirus
PrivacyConcerns
MisleadingApp
PoorPerformance
ReviewResponse
SpamAdvertising
Profanity

Calling the ReportItem API will only fire a PlayStream event under the Event Name, item_reported . This can be
queried using the Data Explorer in the Game Manager. Example queries can be seen below:
The following query returns The total number of repor ts by ConcernCategor y per ItemId in the last 3
days

['events.all']
| where Timestamp > ago (3d)
| where FullName_Name == "item_reported"
| project ItemId = tostring(EventData.Payload.ItemId), ConcernCategory =
tostring(EventData.Payload.ConcernCategory)
| summarize TotalReportCount = count() by ItemId, ConcernCategory
| sort by TotalReportCount desc
| render columnchart kind=stacked

The following query returns All submitted repor ts against a specific ItemId in the last 3 days
['events.all']
| where Timestamp > ago (3d)
| where FullName_Name == "item_reported"
| where EventData.Payload.ItemId == "3f5dd8d4-4ee1-4748-8855-56a8a0277bf9"
| project Timestamp, ItemId = tostring(EventData.Payload.ItemId), ConcernCategory =
tostring(EventData.Payload.ConcernCategory), Reason = tostring(EventData.Payload.Reason), ReportingPlayer =
Entity_Id
| sort by Timestamp

Change the moderation status of an item


You can change the moderation status of a published item using the SetItemModerationState API. An item that
is any state other than Approved will not be accessible on the public catalog for all players. The item creator can
still access the item using the GetItem and GetDraftItems API. Title entities and Admins will be able to see
Non-Approved items through SearchItems , GetDraftItems , and GetItem .
This API can only be called by the title entity . An item Id or AlernateId and a Status must be provided. An
optional Reason free text parameter can also be added. As a service call, that looks something like this:

{
"Status": "AwaitingModeration",
"Reason": "User reports over threshold",
"Id": "3f5dd8d4-4ee1-4748-8855-56a8a0277bf9"
}

By default, a published item will not have a moderation status. Republishing the draft item will not change the
moderation status. The valid Status values are as follows:
AwaitingModeration
Approved
Rejected

The following query returns All items currently in the AwaitingModeration status in the last 3 days

let TimeRange = ago(3d);


['events.all']
| where Timestamp > TimeRange
| where FullName_Name == "item_moderation_state_changed"
| project Timestamp, ItemId = tostring(EventData.Payload.ItemId)
| summarize MaxTimestamp = max(Timestamp) by ItemId
| extend TimeAndId = strcat(MaxTimestamp, "|", ItemId)
| join kind = leftouter (
['events.all']
| where Timestamp > TimeRange
| where FullName_Name == "item_moderation_state_changed"
| project Timestamp, ItemId = tostring(EventData.Payload.ItemId), TargetStatus =
tostring(EventData.Payload.TargetStatus), Reason = tostring(EventData.Payload.Reason)
| extend TimeAndId = strcat(Timestamp, "|", ItemId)) on TimeAndId
| project Timestamp, ItemId, TargetStatus, Reason
| where TargetStatus == "AwaitingModeration"

Delete an item
An item can be deleted by calling the DeleteItem API. This call will remove an item from the draft catalog and
corresponding item from the public catalog (if it has been published). An item Id or AlernateId must be
provided.
{
"Id": "852a2d2b-7754-427e-9ad4-fce2b24a4cef"
}
Adding ratings to your user generated content
5/24/2022 • 4 minutes to read • Edit Online

This guide will go through the API calls that can be used to add a ratings and review system to your game.

Review an item
A rating or review can be attached to an item by calling the ReviewItem API from a client. In order for an item to
be reviewed it must be visible in the public catalog for all players. Ratings and reviews are attached to the player
calling the API and only a single review per player can be associated with an item. The creator of an item cannot
submit a review for their own item. The review is updated every time ReviewItem is called. The following data is
required for the call:
Id : The unique ID of item that is wished to be reviewed.
Rating : A numeric rating the form of a 1 to 5 scale.

In addition, a number of optional parameters can be added also be added:


Title : The title for the review.
ReviewText : A free text field for reviews.
IsInstalled : A flag to indicate if the reviewer has the item.
ItemVersion : The version number for the item being reviewed.

As a service call, that looks something like this:

{
"Review": {
"ItemVersion": "2.4.1",
"Rating": 5,
"Title": "Best Game Ever",
"ReviewText": "I play this game every day. It's my favorite game yet.",
"IsInstalled": true
},
"Id": "3f5dd8d4-4ee1-4748-8855-56a8a0277bf9"
}

A Submitted timestamp is automatically populated and updated when a review is submitted.

Get a player's review for an item


You can get a player's review for an item by calling the GetEntityItemReview API from a client. An item Id or
AlternateId must be provided. A specific ReviewId associated with review will be returned.
{
"code": 200,
"status": "OK",
"data": {
"Review": {
"ReviewId": "730de69c-d6af-f313-4653-09fb14bedeef",
"ItemId": "3f5dd8d4-4ee1-4748-8855-56a8a0277bf9",
"ReviewerId": "title_player_account!218870DE55036998",
"ItemVersion": "2.4.1",
"Title": "Best Game Ever",
"ReviewText": "I play this game every day. It's my favorite game yet.",
"Rating": 5,
"IsInstalled": true,
"Locale": "NEUTRAL",
"HelpfulnessVotes": 0,
"HelpfulPositive": 0,
"HelpfulNegative": 0,
"Submitted": "2021-08-09T06:44:22.569Z"
}
}
}

Calling GetEntityItemReview from a player who hasn't made a review returns a Review object with zeroed
values:

{
"code": 200,
"status": "OK",
"data": {
"Review": {
"ReviewId": "00000000-0000-0000-0000-000000000000",
"Rating": 0,
"IsInstalled": false,
"HelpfulnessVotes": 0,
"HelpfulPositive": 0,
"HelpfulNegative": 0,
"Submitted": "0001-01-01T00:00:00Z"
}
}
}

Get reviews for an item


You can access all the reviews containing text for an item by calling the GetItemReviews API. An item Id or
AlternateId must be provided. Additional optional parameters can be added:

ContinuationToken : An opaque token used to retrieve the next page of items, if any are available.
Count : Number of items to retrieve. Maximum page size is 200. If not specified, defaults to 10.
OrderBy : An OData orderBy used to order the results of the query. Possible values are Helpfulness , Rating ,
and Submitted .

{
"Count": 2,
"Id": "3f5dd8d4-4ee1-4748-8855-56a8a0277bf9",
"OrderBy": "Submitted desc"
}

Submit a helpfulness vote for a review


Players can submit a helpfulness vote for a review by calling the SubmitItemReviewVote API. Submitting a new
helpfulness vote will increment HelpfulPositive or HelpfulNegative depending on the boolean value for the
Vote parameter.

{
"ReviewId": "730de69c-d6af-f313-4653-09fb14bedeef",
"Vote": "Helpful/UnHelpful"
}

Report a review
Players can report a review by calling the ReportItemReview API from a client. A ReviewId must be provided. An
additional optional ConcernCategory parameter can be added.

{
"ReviewId": "730de69c-d6af-f313-4653-09fb14bedeef",
"ConcernCategory": "OffensiveContent"
}

If not specified, ConcernCategory will default to None . The valid ConcernCategory values are as follows:
None
OffensiveContent
ChildExploitation
MalwareOrVirus
PrivacyConcerns
MisleadingApp
PoorPerformance
ReviewResponse
SpamAdvertising
Profanity

Calling the ReportItemReview will only fire a PlayStream event under the Event Name, item_reported . This can
be queried using the Data Explorer in the Game Manager. Example Kusto queries can be seen below:
The following query returns The total number of repor ts by ConcernCategor y per ItemId in the last 3
days

['events.all']
| where Timestamp > ago (3d)
| where FullName_Name == "review_reported"
| project ReviewId = tostring(EventData.Payload.ReviewId), ConcernCategory =
tostring(EventData.Payload.ConcernCategory)
| summarize TotalReportCount = count() by ReviewId, ConcernCategory
| sort by TotalReportCount desc
| render columnchart kind=stacked

Takedown a review
You can submit a request to takedown one or more reviews using the TakedownItemReviews API. This API can
only be called by the title entity . The call takes in a set of reviews that is to be taken down.
{
"Reviews": [
{
"ItemId": "3f5dd8d4-4ee1-4748-8855-56a8a0277bf9",
"ReviewId": "730de69c-d6af-f313-4653-09fb14bedeef"
}
]
}

NOTE
There can be a delay of up to 24 hours until a review is taken down due to the request processing

Ratings design and caching


We have two methods for getting ratings. The difference between the two paths is whether you are interacting
with the review directly or the catalog item.
1. We provide ratings directly (via GetItemReviews , etc.)
2. We provide ratings aggregates in the catalog items (via SearchItems , etc.)

Both routes are asynchronous and have timing delays that it is important to understand.
Direct Ratings (GetItemReviews, etc.)
All these ratings and reviews are served directly. There are two categories of latency here.
1. Individual Reviews - Near Real Time
Individual reviews will not available immediately, but should show up within a few seconds. We expect
that retrying with a backoff will be sufficient for reading a brand-new review.
2. Aggregate Ratings - Under 15 minutes
There's a cache for aggregates
Catalog Item Ratings (SearchItems, etc.)
All these ratings are served as part of the catalog item from our published catalog.
1. Aggregate Ratings - Under 8 hours
The system aggregates the ratings and pushes updates into the catalog which can take anywhere from 4-8
hours.
Settings and Policy Page
5/24/2022 • 3 minutes to read • Edit Online

The Economy Settings page contains various options to configure UGC and Economy features for your game.
These settings can be found under the Economy tab under Title Settings. These settings can also be set and
accessed via APIs using the UpdateCatalogConfig and GetCatalogConfig calls respectively. Note that these APIs
can only be called by title entities.

Catalog Admins and Reviewers


Both admins and reviewers are a collection of player entities.
Catalog Admins
Catalog Admins are players that are given full title-level access to the published and draft catalog. When
accessing items through the SearchItems or GetItem APIs, these players will have read and write access to all
published items including:
Items with a Non-Approved Moderation State
Expired Items (ie. Items with past End-Dates)
Unreleased Items (ie. Items with a future start date)
Hidden Items
All of the above items would not be accessible to a non-admin player via Search.
Admins also have the ability to edit or delete any item in the draft or public catalog.
Catalog Reviewers
Catalog Admins are players that are given the ability to see unreleased content (ie. any published item with a
future star t date )
Reviewers are not able to edit or delete items (except their own content).

Display Properties
Display Properties are custom item properties that can be added to all items in your catalog. Certain properties
can be set in the Display Property Mappings section to be used searches, filters, and orderings when using the
SearchItems API

When you add a field to DisplayProperties , it will create a new index for you in the database. Only documents
added or updated after index creation will be included. If you need the Display Property to apply to all items you
will need to republish the entire catalog.
DateTime , Double , and Queryable String display properties are quer yable , these properties can be used in
Filter and OrderBy statements.
Searchable String display properties are searchable , these properties will be queried with fuzzy search
against the Search field. Searchable properties cannot be used in Filter and OrderBy statements
Titles are limited to 5 display properties of each type.
WARNING
Display property mappings are stored as an indexed list of key-value pairs. Deleting existing display property mappings
can shift indexes and break the behavior of all remaining properties. It is suggested to add an additional property rather
than deleting or editing an existing one and you should avoid deleting property mappings unless absolutely necessary

Content Types
A pre-set list of content types for UGC can be set by providing a list of valid string types. ContentType is an
optional property, but if it is desired to be set, it must be one of the pre-listed values.

Tags
A pre-set list of tags for UGC can be set by providing a list of valid strings. Tags are optional for any item and
an item can contain any number of the pre-listed tags.

Policies
The Policies page allows you to control the client access to the Economy APIs.
Playfab UGC uses the Admin API Policies to control API Access. Please note that if you have or will make any
changes to the JSON, it may break or cause unintentional behavior with the Economy API policies.
Even if it the APIs are enabled, Players are only able to publish, edit, and delete content they have created. Title
Entities are always able to access, delete, and edit any content.

NOTE
Although Admin Players are given title-level edit, delete, and access privileges, they are still considered players for the
purposes of Policies. For example, if the DeleteItem API was disabled for all players, Admins will not be able to delete
content (but titles will continue to be able to)
Item Permissions and Visibility
5/24/2022 • 2 minutes to read • Edit Online

Catalog Items can be given different parameters and values that change whether the item is visible to different
players through the public catalog or other APIs. This document will go over the different states an item can be
in and how it can affect who can see or modify them.

Unpublished Draft Items


These are Draft items that are created using the CreateDraftItem and have not been published. These items are
available to only the Item Creator, Catalog Admins, and Title Entities. Both GetDraftItem and UpdateDraftItem
can be called on these items.

Published Items
Published Items that have a valid start and end date pair (ie. StartDate < CurrentDate < EndDate), are visible to
all players via the Public Catalog. Players can access published items using the SearchItems and GetItem APIs.

Scheduled Items
Scheduled Items are Published Items that have future start date (ie. CurrentDate < StartDate). These items are
only accessible by the Item Creator, Catalog Admins, Catalog Reviewers, and Title Entities. These items will not
show up in the Published Catalog and cannot be accessed using GetItem API for regular players.

Expired Items
Expired Items are Published Items that have past end date (ie. CurrentDate > EndDate). These items will not
show up in the Published Catalog via the SearchItems API but these items can be accessed using GetItem API
for all players.

Hidden Items
Expired Items are Published Items that have the IsHidden flag set to true. These items will not show up in the
Published Catalog via the SearchItems API but these items can be accessed using GetItem API for all players.

Non-Approved Moderated Items


Via the Moderation APIs, Published Items can be set with a moderation status. Published Items that have any
status that is not Approved (ie. AwaitingModeration , Rejected , or Unknown ) are only accessible by the Item
Creator, Catalog Admins, and Title Entities. These items will not show up in the Published Catalog and cannot be
accessed using GetItem API for regular players.
ETags
5/24/2022 • 2 minutes to read • Edit Online

This guide will go through using ETags to manage item updates.

What are ETags?


ETags are a concurrency management option for managing items and their updates.
When creating or updating a Draft item, an ETag will be returned with the success response.
UpdateDraftItem Request

{
"Item": {
"Id": "e08acd29-f28a-4cbb-b8d6-7df74c7f0e4a",
"Type": "ugc",
"AlternateIds": [],
"Title": {
"NEUTRAL": "ETag Test"
}
}
}

UpdateDraftItem Response

{
"code": 200,
"status": "OK",
"data": {
"Item": {
"Id": "e08acd29-f28a-4cbb-b8d6-7df74c7f0e4a",
"Type": "ugc",
"Title": {
"NEUTRAL": "ETag Test"
},
...
"ETag": "\"7800e585-0000-0300-0000-623364bf0000\""
}
}
}

This ETag will be returned from any of the APIs that return the draft item (such as GetDraftItem ,
GetEntityDraftItems , and GetDraftItems ). This ETag will also be updated every time an update is made with
UpdateDraftItem

Using ETags
ETags can be passed in as an optional parameter to UpdateDraftItem and PublishDraftItem calls. If passed in, a
check will be done between the draft item's ETag and the passed in parameter. If the two ETags don't match, the
request will be rejected.
Publish Item Request
{
"Id": "e08acd29-f28a-4cbb-b8d6-7df74c7f0e4a",
"ETag": "\"7800e585-0000-0300-0000-623364bf0000\""
}

The above request would publish the item successfully. While providing any other ETag value would throw an
error and reject the request.
ETags are useful in situations where you're expecting multiple sources to be simultaneously modifying an item
and you want to ensure that no data is overridden by another update.
UGC Pricing Meters
5/24/2022 • 3 minutes to read • Edit Online

PlayFab User Generated Content has two categories of consumption-based meters - Requests and Storage. This
page outlines and defines those meters, including how it is measured and calculated. For more information on
PlayFab's pricing model, see PlayFab Pricing Overview.

NOTE
General usage of PlayFab UGC may contribute toward other PlayFab meters, like PlayStream Events.

Requests
The request meters are determined by the response size of any UGC API calls or CDN requests. For each of the
three PlayFab plans, there are five different rates, depending on the size:

NOTE
Please contact us if you are planning on storing content larger than 100 MBs.

Storage
The storage meter is determined by the total size of all content (both files and images). 5GB is included in all
pricing plans. For additional storage, there is a three different rates for this meter depending on the plan.
This includes content associated with items that haven't been published, and items that aren't visible via the
public catalog. For more information on how items can be hidden from the public catalog, see Item Visibility.

Included Meters
There is a set of included meters for all PlayFab customers, regardless of the selected plan:

M ET ER IN C L UDED A M O UN T

Up to 1 MB Requests 150k requests

Storage 5 GB

NOTE
Studios in Development Mode are required to enter payment information before enabling UGC, and overages will be
charged based on the rates above.

Example Bill
Let's walk through an example customer's UGC consumption and look at their monthly bill. This example title is
on the Pay-as-you-go plan. Let's start with a single user. This user goes to the content discovery page and
searches for 'dinosaurs'. 10 results are displayed to the user, each with a title and thumbnail image. The user
selects a piece of content, which displays the full metadata, including the description, ratings, and 4 more
images. The user decides the content looks interesting enough, so they select the download button.
Now let's see what meter consumption this scenario just drove:
This user goes to the content discovery page and searches for 'dinosaurs'. 10 results are displayed to the
user, each with a title and thumbnail image.
The SearchItems call returned 10 items with the base metadata, resulting in a single Up to 1 MB
Request .
Each of the 10 thumbnails is requested from the CDN. Let's pretend 5 of these are just under 1 MB,
and 5 are just over 1 MB. This results in 5 Up to 1 MB Requests and 5 Up to 5 MBs Requests .
The user selects a piece of content, which displays the full metadata, including the description, ratings, and 4
more images.
The GetItem call returned a single item with the full metadata, resulting in a single Up to 1 MB
Request
The GetRatings call returned a single item's ratings, resulting in a single Up to 1 MB Request
Each of the 4 images is requested from the CDN. These are higher quality images, so let's pretend 2 of
these are just under 5 MBs, and 2 are just over 5 MBs. This results in 2 Up to 5 MBs Requests and 2
Up to 25 MBs Requests .
The user decides the content looks interesting enough, so they select the download button.
This content is requested from the CDN. This is a large piece of content, so let's pretend it is 20 MBs.
This results in a single Up to 25 MBs Requests .

M ET ER REQ UEST C O UN T

Up to 1 MB 8

Up to 5 MBs 7

Up to 25 MBs 3

Up to 50 MBs 0

Up to 100 MBs 0

Now let's pretend this title has 10 thousand users that perform this exact same scenario once a day in a 30-day
month (300 thousand times) - this is roughly the same as a single user performing this exact same scenario on
average once every 9 seconds. This would result in the following meter consumption:

M ET ER REQ UEST C O UN T

Up to 1 MB 2.4 million

Up to 5 MBs 2.1 million

Up to 25 MBs 0.9 million

Up to 50 MBs 0

Up to 100 MBs 0

Let's also pretend this is the only title leveraging UGC in the studio, and the title has 4 GB of UGC stored (which
is fully covered by the 5 GB included, so no charges are incurred on the Storage meter). If this were the total
consumption at the end of the month, here is what the final UGC bill would look like:

Additional resources
For the most up-to-date view of prices per meter, see PlayFab.com/Pricing
See Consumption Best Practices to learn how to maintain the lowest rate of meter usage and cost for your
game
Limits
5/24/2022 • 2 minutes to read • Edit Online

The purpose of this guide is to detail the limits that are enforced when creating, updating, and reading from
your catalog of items.

Item Creation/Updates
Binary Content Size
Files or images that are greater than 100MB in size cannot be added to items. It is recommended that larger
files are split into several smaller partitions if possible.

NOTE
Please contact us if you require storing content larger than 100 MBs.

Binary Content Quantity


Up to 100 images and 100 files can be added to an item. Files have no restrictions while only .png, .jpg, .gif,
and .bmp file types can be uploaded as images.

NOTE
Each blob should only be used in one item. If you wish to have a piece of content repeated in multiple items, you should
re-upload the content to different blobs.

CreateUploadUrls
Content blobs/urls will be garbage collected after 24hrs if not attached to a draft or published item.
Item Updates
These limits affect calls to APIs that create items or modify existing item properties (such as UpdateDraftItem ,
CreateDraftItem , and DeleteItem )

Title entities are limited to 1000 requests over 10 seconds


Players are limited to 10 requests over 30 seconds

Item Reads/Searches
RPS Limits
These limits affect calls to APIs that query items and their properties (such as SearchItems , GetItem , and
GetDraftItem )

Title entities are limited to 10000 requests over 10 seconds


Players are limited to 100 requests over 60 seconds
Maximum Page Size
The following are the maximum count of items returned for the various APIs. You can use continuation tokens to
paginate through results that return greater than the limit.
SearchItems - 50 Items
GetDraftItems - 25 Items
GetItems - 25 Items
GetItemReviews - 25 Items

Filter Complexity
There are checks enforced to prevent the use of overly complicated Filter queries used in SearchItems calls.
More information can be found here

Item Metadata
Titles
Titles have a 512 character limit per country code.
Descriptions
Descriptions have a 10000 character limit per country code.
Keywords
Keywords have a 50 character limit per keyword and up to 32 keywords can be added per country code.
Display Properties
The Display Properties field has a 10000 character limit .
Tags
Tags have a 32 character limit per tag. Titles can have a maximum of 1024 Tags and up to 32 Tags can be
added to an item
Content Types
Content Types have a 32 character limit per content type. Titles can have a maximum of 128 Content Types .
User Generated Content (UGC) Tutorials
5/24/2022 • 2 minutes to read • Edit Online

These tutorials demonstrate features that you can use to create and maintain the economy of your game.
Publish your first user generated content
Publish your first user generated content
5/24/2022 • 7 minutes to read • Edit Online

This tutorial walks you through publishing UGC with content through both APIs and the Game Manager UX,
diving into more detail than the quickstart.

Requirements
A PlayFab developer account
A UGC-enabled title

Via APIs
In this section, we will leverage the Postman Collections to interact with the PlayFab UGC APIs, but you can
leverage any of our SDKs.
Create Blob URLs
The UGC system works with the PlayFab Entity Model, so we need to use entity tokens instead of session
tickets to call these APIs. You can learn how to get a title entity token in the Postman Collections
Quickstart.
The UGC system leverages Azure Blob Storage to store all content (files and images) associated with your
title's UGC. To upload the content, we first need to call the CreateUploadUrls API, passing in the file names
and sizes (in bytes) to create the new blobs. For example, if I wanted to upload a text file and PNG image, I
would pass in the following to the request body:

{
"Files": [
{
"FileName": "HelloWorld.txt",
"FileSize": 12
},
{
"FileName": "PlayFabLogo.png",
"FileSize": 20725
}
]
}

The response will include an Id and Url for each piece of content:
{
"code": 200,
"status": "OK",
"data": {
"UploadUrls": [
{
"Id": "[Content ID]",
"Url": "[Content Url + '?' + Token]",
"FileName": "HelloWorld.txt"
},
{
"Id": "[Image ID]",
"Url": "[Image Url + '?' + Token]",
"FileName": "PlayFabLogo.png"
}
]
}
}

NOTE
Each create token (returned in the "Url" field of the response) is valid for 6 hours, after which you will not be able
to upload content to the blob. If you did not upload any content to the blob, it will get cleaned up by our service
and you will need to create a new blob by calling CreateUploadUrls again. This URL will also not allow access to
content until is has been uploaded to a draft item where it will receive a different (now publicly accessible) URL

NOTE
Each blob should only be used in one item. If you wish to have a piece of content repeated in multiple items, you
should re-upload the content to different blobs.

Upload Content to Blobs


There are a few different ways to upload your content to these URLs
Via Postman
Create a PUT request with the URL generated from calling CreateUploadUrls and by adding the
comp: blob and x-ms-blob-type: blockblob as headers:
Then you can upload the file by selecting binary as the Body type:

Via AzCopy
Another option is using the AzCopy tool. You can download the tool and get started with AzCopy here.
In your terminal of choice, call azcopy with the following parameters:

[relative path to azcopy.exe] copy [relative path to local content] [Url + '?' + Token]

Create the Draft Item


Now that the files and images have been successfully uploaded, you can call CreateDraftItem , passing in the
URLs of the content and images, to create your first item in the draft catalog:

{
"Item": {
"Type": "ugc",
"Title": {
"neutral": "Hello World!"
},
"Description": {
"neutral": "My first UGC item (with content!)"
},
"ContentType": "Game Item",
"IsHidden": false,
"Contents": [
{
"Id": "[Content ID]",
"Url": "[Content Url]"
}
],
"Images": [
{
"Id": "[Image ID]",
"Type": "Thumbnail",
"Url": "[Image Url]"
}
]
},
"Publish": false,
"AllowOverwrite": false
}

NOTE
When uploading images to items, every image must be classified with a Type parameter. This can either be a
"Thumbnail" or a "Screenshot". Each item is limited to only one image of a "Thumbnail" type and by default, Searches will
return the "Thumbnail" image (if it exists) by default.

The response will return the metadata you passed in, along with an item ID:
{
"code": 200,
"status": "OK",
"data": {
"Item": {
...
"Id": "e5427509-1b72-4ee1-9e6c-03fc055a94f3",
...
}
}
}

NOTE
The content/image URLs returned by the created draft item and the original CreateUploadUrls call will be different.
Regardless of how you chose to upload content, you can test that the upload was successful by copying the base Url
(before the '?') and navigating to it in your browser. This will only return the image after it has been uploaded to a draft
item, not by using the URL from CreateUploadUrls .

The draft UGC item now exists in the draft catalog! As long as the UGC item is not yet published, it will
not be searchable via the public catalog. You can find this UGC item by calling either of the following APIs:
GetDraftItem , passing in the item ID obtained from the CreateDraftItem response
GetDraftItems , passing in a list of known item IDs
GetEntityDraftItems, passing in an Entity ID and/or passing in the ContinuationToken from each
previous response to page through the list of draft items

NOTE
If you wanted to publish immediately, you could change the Publish field to true

When you are ready to publish the UGC item, call PublishDraftItem , passing in the item ID (obtained
from the CreateDraftItem response).
If your UGC item contains multiple particularly large files, publishing the item can take some time, and
when there are many other players concurrently uploading content, this process can take even more
time. You can check on the status of the publish by calling GetItemPublishStatus , passing in the item ID
(obtained from the CreateDraftItem response). There are a few possible statuses:
Succeeded - the UGC item has successfully published
Pending - the UGC item is still in the process of getting published
Failed - the UGC item publish failed and will not get published until the offending content has
been modified
Unknown- this is the default status, and will be returned before calling PublishDraftItem on the
UGC item
Canceled - an internal error has occurred, please try publishing the item again (if you see this
status multiple times, please reach out to the PlayFab engineering team)
Once the UGC item has been successfully published, you can search for it via SearchItems or grab it
directly via GetItem if you have the item ID.
You can make changes to the UGC item before or after publishing by doing the following:
Call GetDraftItem , passing in the item ID (obtained from the CreateDraftItem response)
Copy the UGC item's data (everything in the data field)
Call UpdateDraftItem , passing in the modified UGC item's data
If you want to update any of the files or images, you would need to create another blob by calling
CreateUploadUrls again

Republish the UGC item by calling PublishDraftItem

Via Game Manager


In this section, we will create a UGC item completely within the Game Manager experience - no code necessary!
Create the Draft Item
Navigate to the UGC page by selecting Economy > Catalog (Preview) .
Select New item .
Fill out the appropriate metadata for your UGC item:

F IEL D N A M E VA L UE

Entity type title_player_account

Entity ID [your player ID]

Content type Game Item

Start date [any date in the past]

Title { "neutral": "Hello World!" }

Description { "neutral": "My first UGC item (with content!)"


}

Under the Files and Images sections, upload the appropriate content by selecting the Upload button.
Select Save and publish .
The UGC item will now automatically be created as a draft item and published to the public catalog - you
will now be able to find this item in the table with other published UGC items.

NOTE
There is currently no way to check the draft item or publishing status within Game Manager - this can only be done via
the APIs

If you want to make any changes to the published UGC item, you can do so by doing the following:
Select the published UGC item from the table
Make the appropriate edits
Select Save and publish

Troubleshooting
Invalid Request - The content type 'Game Item' is not supported.
If content types have been specified in your title's config (either through GetCatalogConfig /
UpdateCatalogConfig or in Game Manager under the Economy Settings tab), you will need to add
Game Item to the list, or change the content type to one your title already supports
Invalid Request - This title is not configured to use this service.
Your title currently has UGC disabled - you can enable this by updating your title's config (through
GetCatalogConfig / UpdateCatalogConfig , in Game Manager under the Economy Settings tab, or by
navigating to the Economy > Catalog (Preview) tab and selecting Enable )

Next Steps
You now have published UGC items in your catalog! You can leverage SearchItems to create content discovery
experiences for your players.
Search Tutorial >
What is PlayFab Engagement?
5/24/2022 • 2 minutes to read • Edit Online

PlayFab Engagement is a set of tools to engage your player community and keeping them coming back for
more. The features are Title news, Email templates, Push notifications.
Title News enables broadcasting of updates as news to your player base. It can be used to inform users of
upcoming events, share release notes for a recent update, or disseminate any other information you want your
players to have. To get started, see the Title news Quickstart.
Email messaging allows you to send customized emails to players basd on predefined schedule, rules based on
PlayStream event, or by calling an API. Emails are fully customizable with HTML templates which can include
player profile properties. To get started, see the Email templates Quickstart.
Push notifications let's you to send unlimited customized messages to players' home screens in real time. To get
started, see the Push notifications Quickstart.
News
5/24/2022 • 2 minutes to read • Edit Online

Title News is a mechanism for broadcasting information to your players. It allows you to post updates about
things such as upcoming in-game events, patch notes, future downtime, community activity, or anything else
you'd like your players to know.
Each post contains a few basic elements:
Title
Date
Status
Body
Posts can be published and made available to users immediately upon creation, or scheduled to go live at a time
in the future. After publishing posts in PlayFab via Game Manager or the AddNews API, your client can call
GetTitleNews to retrieve a list of all active posts and then display them to the user however you choose.
Title News quickstart
5/24/2022 • 4 minutes to read • Edit Online

Title News is a mechanism for communicating with your players for patch notes or big events your game may
be hosting. It contains a few basic elements:
Date
Status
Title
Body
Language(s)

NOTE
The Body element is a string which can contain raw text or JSON.

Requirements
This quickstart builds on information presented in other topics. Please refer to the topic links that follow if you
have questions.
You should be familiar with the PlayFab Game Manager.

NOTE
You must already have a title default language set to continue with localized title news.

Title news can now be localized. For details on working with the default languages in your title and with the
preferred languages for your players, please review the Setting Default Languages tutorial. Remember - to
continue with localized title news, you must have title default language set accordingly.
PlayFab supports storing localized strings on behalf of game developers, by associating a title and body with a
language for a title news entry.
We have added the necessary logic to provide your players with the correct strings for the language they prefer.
When the client queries for title news, they will receive different versions of title news, based on the players
preferred language. You can add multiple translated versions to a single title news entry.

Creating Title News entries


There are two ways to create Title News entries:
1. Via Game Manager.
2. Using the Admin API method AddNews.
Creating title news with Game Manager
To create title news entries with Game Manager :
Navigate to your title -> Content -> Title News -> New Title News as shown in the following image.
For the purposes of this tutorial, we will assume your title's default language is English. This means that you
must add strings for your default language before you can save the title news.
Adding more languages is as simple as clicking on ADD L ANGUAGE , choosing the language you want to add,
and then typing in the localized strings. Select the Save Title News button, and your entry is created.
The timestamp is the time that players will see next to the title news. The timestamp is automatically set to the
system date at the moment you select the Save Title News button, but you can also set it manually. After
saving the title news page, you'll be redirected back to the page that contains the list of your title news entries.
Creating title news using the PlayFab Admin API
You can create title news by calling AddNews method. Using this Admin API allows you to specify a custom
timestamp. News added this way is immediately published. You can then add localized content to the item you
just created by calling AddLocalizedNews, with the news ID returned from the AddNews method.
The code example that follows demonstrates this.
void CreateNews() {
PlayFabAdminAPI.AddNews(new AddNewsRequest {
Timestamp = new DateTime(2014, 1, 8, 12, 0, 0), // Any date - This one is the founding of PlayFab
Title = "My Second News",
Body = "This is my second news post."
},
result => Debug.Log("News post added!"),
error => Debug.LogError(error.GenerateErrorReport()));
}
void CreateNews() {
PlayFabAdminAPI.AddLocalizedNewsRequest(new AddLocalizedNewsRequest{
NewsId = "74623b12-6c80-ee4b-7c3b-58e638aa62bd",
Language = "de"
Title = " Meine zweite Nachricht",
Body = " Dies ist meine zweite Nachricht."
},
result => Debug.Log("Localized news post added!"),
error => Debug.LogError(error.GenerateErrorReport()));
}

Reading title news


The GetTitleNews method makes reading the title news very easy. The method returns all published title news
entries and does not return archived and unpublished entries.
Calling GetTitleNews from the client API will return the news entries in the preferred language of the player, if
the title news item has added localized content in that language, or in the title default language.
Calling GetTitleNews from the server API will return the news entries in the title default language.

void ReadTitleNews() {
PlayFabClientAPI.GetTitleNews(new GetTitleNewsRequest(), result => {
Debug.Log("Got latest news!");
// Process news using result.News
}, error => Debug.LogError(error.GenerateErrorReport()));
}
void ReadTitleNews() {
PlayFabServerAPI.GetTitleNews(new GetTitleNewsRequest(), result => {
Debug.Log("Got latest news!");
// Process news using result.News
}, error => Debug.LogError(error.GenerateErrorReport()));
}

Updating an existing title news entry


The content of a title news entry can only be modified in Game Manager.
To locate and select the entry you wish to modify in Game Manager :
Go to the menu on the left and select Content .
Go to your Title News tab.
Select Existing Entr y .
To make your updates, save them, and optionally add localized versions:
Update the Title , Status , or Data for the entry.
Select the Save Title News button.
If you are updating a title news entry that only has a title and body in a single language, you can now add
localized versions of this title news by selecting Add Language .
If you plan to post unpublished entries for a future release, this will be the way you transition them through a
published and archived state. Updating title news also lets you fix typos.

Deleting title news


Once an entry is no longer needed, you can delete it in the Game Manager .
Find the entry you wish to modify, then:
Navigate to your Title .
In your menu on the left, select Content .
Go to Title News .
Put a check in the checkbox for the Existing Entr y .
Select the Title News entries you wish to delete and choose X Delete Title News .
News Tutorials
5/24/2022 • 2 minutes to read • Edit Online

This tutorial shows you how to set a default language for your title and for your players.
Setting default languages
Setting default languages
5/24/2022 • 5 minutes to read • Edit Online

PlayFab is introducing support for storing localized strings on behalf of game developers. In addition, we are
adding the necessary logic to provide your players with the correct strings for the language they prefer.
To accomplish this, we will be leveraging two new language settings: one is associated with your title, and the
other is stored on each of your players' entity profiles:
1. Title default language : Indicates your title's primary supported language. Once set, we will require your
title to support this language to be used at least for features using localized strings.
2. Player language : Indicates the player's preferred language. This can be set on a per-title basis.
Using these two settings, PlayFab logic will match up localized strings with the players who prefer that language.
Players without a language preference will receive strings in your title's specified default language.

NOTE
Players with a preference for a language that your title doesn't support will also receive strings, based on your title's
default language.

This tutorial walks you through how to set the default language of your title and the preferred language of your
players.

Requirements
This tutorial assumes you have the following working knowledge about using PlayFab:
A basic knowledge of how to create a player. This is necessary, because players must already exist with a
username and password before calling preferred language logic. Refer to Getting started for developers
for information on creating a player for the title.
That you have read the Game Manager quickstart if you were unfamiliar with the Game Manager, as it is
the place where language information is viewed.
That you have knowledge of how to work with player profiles, as it will be necessary to confirm that a
preferred language has been added to a player's profile.
Please take a moment to review the information provided on how to get a player's profile in the Getting
player profiles tutorial.

Section 1 – Player's preferred language


Before setting your player's preferred language, figure out how you want to collect it. You have a couple of
options:
Ask them: Add an option on your game's menu.
Intuit their language: Use the language of the player's device by calling the provided platform API (for
example, Locale.getDefault.getLanguage() for Android).
NOTE
There are a lot of languages out there, and your title may not support them all. While not required, we recommend
future-proofing your title, and storing the player's actual preference. If you come back and add support for that language
later, PlayFab's logic will automatically start serving up the new strings (rather than the default).

Step 1 – Set the language


PlayFab allows you to choose from a specific list of languages to support. You can make a call to the
GetLanguageList() method to see the language codes.

NOTE
When using the SetProfileLanguage API, the language string must be specified in the ISO 639-1 format (for example,
"en", "es", or "ja"). At the current time, the code "zh" is not supported.

First, we will update a player's profile to include the language in which they would prefer to get content from
your title.
C# Code Example

void SetProfileLanguage(string language, int? profileExpectedVersion, EntityKey entity)


{
var request = new SetProfileLanguageRequest
{
Language = language,
ExpectedVersion = profileExpectedVersion,
Entity = entity
};
PlayFabProfilesAPI.SetProfileLanguage(request, res =>
{
Debug.Log("The language on the entity's profile has been updated.");
}, FailureCallback);
}

void FailureCallback(PlayFabError error)


{
Debug.LogWarning("Something went wrong with your API call. Here's some debug information:");
Debug.LogError(error.GenerateErrorReport());
}

Step 2 – See that the language was updated


Go to the player's overview. In Game Manager, go to Player -> Over view , and see that their contact info
section is updated with their preferred language.
The language can also be updated with the Language dropdown menu displayed in the following image.
Next, you can navigate to the player's PlayStream , and it will show an Entity language updated event.

Selecting the info icon on the event should show JSON similar the example shown below.
{
"EventName": "entity_language_updated",
"Source": "PlayFab",
"Language": "en",
"EntityChain": "title_player_account!4CDA57A14A596E70/<YourTitleId>/C9458B4D3A115F4B/36163DA3783B0C8A/",
"EntityLineage": {
"NamespaceId": "4CDA57A14A596E70",
"TitleId": "YourTitleId",
"MasterPlayerAccountId": "C9458B4D3A115F4B",
"TitlePlayerAccountId": "36163DA3783B0C8A",
"CharacterId": null,
"GroupId": null
},
"EventNamespace": "com.playfab",
"EventId": "f643e22a2a76462aaeaa3469afa31434",
"EntityType": "title_player_account",
"EntityId": "36163DA3783B0C8A",
"SourceType": "BackEnd",
"Timestamp": "2018-08-24T18:49:47.8755292Z",
"History": null,
"CustomTags": null,
"Reserved": null
}

Section 2 – Set a title default language


The next thing we will do is set a default language for your title. All localization features will now associate a
language with every translated version of the content.
The title requires a default language. This ensures that if any player's preferred language isn't set or supported,
the player can still receive the default version of the content.
To begin, select Settings in the menu to the left, as shown below.
In the General tab under the new TITLE DEFAULTS header, you will see the Default language dropdown. You
must set a default language before you can use any of the add localization features.
When you are done, select the SAVE button, and message will appear stating that your update was successful.
If you return to the dashboard, you will see a Title API settings changed event in your PlayStream event list,
as shown below.

Selecting the info icon on the event should display JSON similar to the example provided below.
{
"EventName": "title_api_settings_changed",
"PreviousSettingsValues": {
"DefaultLanguage": null
},
"SettingsValues": {
"DefaultLanguage": "en"
},
"UserId": "EAF83D52E282C291",
"DeveloperId": null,
"EventNamespace": "com.playfab",
"EntityType": "title",
"Source": "PlayFab",
"EventId": "108849a5e1424051b42256bc75b2e34b",
"EntityId": "YourTitleId",
"SourceType": "BackEnd",
"Timestamp": "2018-08-24T21:51:02.2215614Z",
"History": null,
"CustomTags": null,
"Reserved": null
}

Section 3 – Updating a title default language


It is important to remember that setting a default for your title tells PlayFab to use that language when you issue
communications to players who don't have a preferred language set or who have chosen a language which
doesn't match one you support.
Because the title's default is used as a fallback language, PlayFab will expect that all your communications
support your default language.

NOTE
You can always change your title default, but PlayFab will require that your current communications templates support
the language you're changing to.

If you update your title's default language, you'll see that the interface now shows an Edit link.

Following this link, you will see the same drop-down as before. However, if you try to save a default language
that isn't fully supported by your email templates, you will see one or more error messages like the one shown
below.
If there are errors, you can follow the links provided to update your content to support the language which is
missing. When all errors have been addressed, the default language change will be accepted.

Conclusion
In this tutorial, you've seen how to set and update your title's default language and your players' preferred
language.
If you have any questions or feedback on this tutorial, please contact us through our forums or slack channel.
Push Notifications
5/24/2022 • 2 minutes to read • Edit Online

Push notifications give games a channel to send immediate customized messages to a player’s device - even
when the player is not currently running the game.
Notifications might be used to indicate that a user has received a message, that some update is available in
game, or that the user needs to take some action. When used properly, they can be a very effective tool for
improving your game’s retention by drawing players back into your game at key moments before churn.
Using PlayFab's push notifications feature, developers may send unlimited push notifications to any number of
devices completely free of charge.
The following screenshot is an example from an Android device's notifications area showing a push notification.

As a best practice, you should tell players up front how you will be using the push notification service - including
the value the notifications will provide to the player before they are given a system OS prompt to allow or
disallow them.
Explaining how your game rewards or communicates via push notification can be the difference between
building community engagement and driving players away. For more information about push notification best
practices, check out this blog post.
Push notifications quickstart
5/24/2022 • 4 minutes to read • Edit Online

Push notifications from PlayFab are enabled by a linkage of three major systems:
1. The player’s device OS (Android, iOS, etc.)
2. The vendor-specific channel (Google, Apple, etc.)
3. Cross-platform message routing (PlayFab via Amazon Simple Notification Service [SNS]).

NOTE
If any of these systems are unlinked, clients will stop getting notifications. It is fairly simple to accidentally change one of
the three systems, and wind up breaking the link. Furthermore, it is difficult to know at any individual point in the flow if
all of the systems are configured properly.

The PlayFab push routing system


Every PlayFab title can enable one Google (GCM), and one Apple Push (APNS, APNS_SANDBOX) notification
channel at a given time. These can be configured in one of two ways:
1. Using the UI in Game Manager under Settings -> Push Notifications .
2. Using the PlayFab Admin API - SetupPushNotification.
For more detailed setup information, read these tutorials:
Push notifications for Android
Push notifications for iOS

Push messages in-game


Push messages will vary based on the development engine/platform. However, the easiest way to receive push
notifications is using a Unity project with our SDK and the Firebase Cloud Messaging (FCM) plugin for Android,
or just Unity for iOS.
Receiving push on Android - This requires a plugin. The best supported plugin is the native FCM plugin.
Receiving push on iOS - This does not require a plugin for basic push messages.

TIP
Please see the FCM documentation for instructions on how to set up the FCM Unity plugin, or push on Android Studio.

Testing the setup


After configuring your title and client, you can test your configuration using the PlayFab server API -
SendPushNotification. This API allows you to send as many push notifications as needed at no extra cost.
You can use the PlayFab CloudScript service as a quick and secure server API environment. From there, push
notifications can be sent as needed.
To use this method to test your configuration, upload or append the code in the following example to your title’s
CloudScript.
Example
Consider the following scenario:
Players in your title may access a leaderboard based on rank statistics.
Each player may pay 1 CH currency, and challenge another player who is up to 5 positions away from the
current player.
First, consider a virtual currency as shown in the example screenshot below (see the Currencies tutorial for
information on how to define a virtual currency).

Now, consider the following statistics defined for each player (see the Accessing Archived Tournament Results
tutorial for information on how to generate a test leaderboard).

Once you've set up these prerequisites, you can set up a push notification challenge system.
The following client code will call the CloudScript ChallengePlayer .
public void ChallengeRandomClosePlayer(string currentPlayerId) {
PlayFabClientAPI.GetLeaderboardAroundPlayer(new GetLeaderboardAroundPlayerRequest() {
MaxResultsCount = 10,
StatisticName = "Rank",
PlayFabId = currentPlayerId,
}, result => OnLeaderboardLoaded(result,currentPlayerId),OnPlayFabError);
}

private void OnLeaderboardLoaded(GetLeaderboardAroundPlayerResult leaderboard, string currentPlayerId) {


var index = (int)(UnityEngine.Random.value * (leaderboard.Leaderboard.Count-1));
if (leaderboard.Leaderboard[index].PlayFabId == currentPlayerId)
index = (index + 1) % leaderboard.Leaderboard.Count;
var targetId = leaderboard.Leaderboard[index].PlayFabId;

PlayFabClientAPI.ExecuteCloudScript(new ExecuteCloudScriptRequest() {
FunctionName = "ChallengePlayer",
FunctionParameter = new Dictionary<string, object>() {
{ "TargetId", targetId }
}
}, null, OnPlayFabError);
}

public void OnPlayFabError(PlayFabError obj) {


Debug.Log(obj.GenerateErrorReport());
}

The ChallengePlayer CloudScript code will handle the request, validate the leaderboard state, and send the
challenge push notification to the target.
handlers.ChallengePlayer = function (args) {
var targetId = args.TargetId;
var leaderboard = server.GetLeaderboardAroundUser({
MaxResultsCount : 10,
PlayFabId : currentPlayerId,
StatisticName : "Rank"
});

for(var i = 0; i < leaderboard.Leaderboard.length; i++) {


var target = leaderboard.Leaderboard[i];
if(target.PlayFabId !== targetId) continue;

// subtract virtual currency from current player


server.SubtractUserVirtualCurrency({
VirtualCurrency : "CH",
PlayFabId : currentPlayerId,
Amount : 1
});

// get current player profile


var profile = server.GetPlayerProfile({
PlayFabId : currentPlayerId
}).PlayerProfile;

// try to send push notification


try {
server.SendPushNotification({
Recipient : targetId,
Package : {
Message : `${profile.DisplayName} challenges you for a battle!`,
Title: "You have been challenged",
}
});
} catch (ex) {
// Target player has not registered for Push Notifications
}
return;
}
}

Push notification usage


Having the ability to use push notifications is an awesome power. When abused, however, it can cause users to
opt out of future notifications - or even leave a game entirely.
If used judiciously, though, push notifications can be one of your best tools for building and maintaining your
game community.
Push notifications are a fire and forget message protocol which does not guarantee delivery.

NOTE
Remember that there is no guarantee that your players will receive, open, or engage with your message. Given that
caveat, it is a good practice to use messages as bonus functionality, rather than as a critical part of your gameplay loop.

For iOS platforms, apps are given a one-time dialog prompt from the OS, allowing the user to determine the
status of push notifications. After the user has made their initial selection, this setting will persist until:
The App is updated or reinstalled.
The user makes changes to the settings from their phone’s settings menu.
For Android apps, notifications are enabled by default, and can be turned on and off at will from the client.

TIP
It is a good practice to re-initialize your notification listeners with every session.

Resources
The following resources provide additional information about the topics in this quickstart:
Firebase Unity SDK: An all-in-one FCM solution for Unity. This SDK, among all other features, allows you to
receive and process push notifications sent via FCM.
Push It Real Good: How to Get Players to Say Yes to Push Notifications: This blog post details additional
strategies and techniques for using push notifications.
Push Notifications: This blog post describes the most recent upgrade in Push functionality, and switching to
FCM as the primary plugin for Android.
Postman Quickstart: This quickstart shows you how to test our APIs using Postman.
Push notifications tutorials
5/24/2022 • 2 minutes to read • Edit Online

These tutorials have been designed to instruct you on how to use push notifications.
Getting Started with Android Push Notifications
Push notification templates
Push Notifications for Android
Push Notifications for iOS
Getting Started with Android Studio and push
notifications
5/24/2022 • 11 minutes to read • Edit Online

Overview
This tutorial has been designed to help you get up and running with Android PlayFab integration with push
notifications.
Push notifications require a configuration in several systems. Before getting started, let's talk about how the
infrastructure works. There are 4 entities participating in the process:
1. Google Play Ser vices
2. Firebase Cloud Messaging Ser vice s (FCM , built on top of the old Google Cloud Messaging .)
3. PlayFab Ser vices
4. Client Applications
1. Google Play Services
Google Play Services identifies your page on the play market using a package name.
An example of this would be: com.bob.games.matchthree .
When registered in Google Play, the package name becomes a unique application ID and serves many purposes,
from installing through play store to preventing impersonation.
2. Firebase Cloud Messaging (FCM )
Firebase Cloud Messaging services offer you a cloud-based system to send, direct, and deliver your push
notifications.
It also allows other services (like PlayFab) to send push notifications on your behalf using the FCM server key.
3. PlayFab Services
PlayFab Services then uses the FCM server key to send push notifications to your clients.
4. Client Services
Finally, your client application may receive notifications and process them as needed.
Four -way split
As a result of this, we need to set up 4 different systems. To do this, our tutorial is split into 4 chapters, covering
the configuration for each piece.

NOTE
The order that you use to configure the systems is important.

Prerequisites
You must have a Google account.
You must have a PlayFab account.
A generated notification icon using the Android Asset Studio Notification icon generator.
Scenario
In this section of our tutorial, we will be assembling an application called the Foo PlayFab App. It is an Android
app that has the following functions:
It signs into PlayFab using an Android Device ID.
It receives push notifications from PlayFab.
Our package name will be com.foo.playfab.app.

IMPORTANT
Make sure to use your own package name and title when following this tutorial.

Chapter 1: Configuring Firebase


You start configuring Firebase by using its official console page. You will be presented with a page where you
can add a new project.
To do this, select the Add project area, as shown in the following picture.

You will be asked to provide a Project Name (in this tutorial we use our Foo PlayFab App , but make
sure to come up with your own name when following this tutorial).
Select the Create Project button to advance to the next step.
You will be redirected to the New Project Dashboard .
Add a new Android Application to the project by selecting the area as shown in the following picture.
A new Application requires 3 steps to be added.
1. First, you must provide an Android Package Name . We are using com.foo.playfab.app , but make
sure to come up with your own Package Name when following this tutorial.
2. Select the Register App button to move to the next step.
Step 2 allows you to download a settings file called google-ser vices.json . It will be used later in the App to
automatically configure Google services.
After you download it, select the Continue button to move to the next step.
3. The final step offers information on how to set up your build process to wire up the Firebase and Google Play
SDKs.

NOTE
You may ignore this information, as we will be using an automated tool built into the Android studio that performs this
setup automatically.

Select the Finish button to proceed.


Once the Application has been added, it will appear on the dashboard.
At this point, configuration is complete, and we need to extract the FCM server key (which we will use to
wire up PlayFab push notifications).
Go to the Project settings as shown in the following picture.
In Project settings , navigate to the Cloud Messaging tab.
Locate the Ser ver Key area (the red area in the picture shown below).
Copy this Key and store it in a safe and easily accessible place.

At this point, we have done everything we need in Firebase to enable push notifications.
Chapter 2: Configuring the Google Play console
When your app is ready, you will most likely create a Google Console Project to maintain a product Play Store
page. Let's go though the process of creating a GooglePlay Project, and linking it to the Firebase Project.
Start by visiting the Google Play Console page and creating a new project as shown in the following picture.
Assign the Title .

NOTE
In this example, we use Foo PlayFab App . Please make sure to come up with your own title and package name while
following this tutorial.

Select the Create button to continue.

The Google Play Console Project page will open.


Select Ser vices & APIs on the side menu.
The Ser vices configuration page will open.
Locate the Firebase Cloud Messaging panel.
Select the Link a Sender ID button, as shown in the following picture.
To link the Sender ID :
Use the FCM server key that you received (and saved) while using the Firebase console in the previous
Chapter.
When done, select the Link button, as shown in our example.

Take a moment to verify that the Sender ID displayed in the Google Play Console matches the one from
the Firebase Console , as shown in the example below.
At this point, the Google Play Console Project is successfully linked to the Firebase Project .
Chapter 3: Configuring the PlayFab title
The purpose of this chapter is to show you how to configure PlayFab Services, so that it can send push
notifications to the player on your behalf.
First, you must go to Title settings in your title's Settings menu.
Select the Push Notifications tab.
For the Android option, select the Settings icon.

You will be asked for your Google ser ver API key .
Copy the one you received through the Firebase console, as shown in the example provided below.
If everything is correct, you will be presented with a page that shows Push Notifications as Active .

This concludes configuring your PlayFab title.


Chapter 4: Configuring Android studio project
In order to utilize the PlayFab JavaSDK, you will need the PlayFab Client JavaSDK and its dependency, Google
GSON.
Download the PlayFab client JavaSDK JAR library here.
Look for client-sdk-*.jar , and the corresponding Java Doc if you need it.
Download the latest Google GSON.
Look for gson-*.jar .
Have the previously mentioned .jar files nearby.
Start by creating a regular Android studio project.
Verify that the Package name matches the one you used throughout this tutorial (in Firebase, for
instance).
NOTE
For our purposes in this example, we are using com.foo.playfab.app , but please remember to come up with
your own package name and title while following this tutorial.

Select a Minimum SDK to your choice.


Then select the Next button.
For this tutorial, we suggest using the Empty Activity template to begin with.
Select the template you want to use.
Then select the Next button.
Configure the template as you want.
Select the Finish button.
Once you open the newly created project:
Switch to the Project tab (1) .

NOTE
In the previous Chapter, you downloaded the google-services.json configuration file from the Firebase console. Use
this for your next step.

Verify that this file is placed under the App folder (2) .
Then, navigate to Tools (3) .
Select Firebase (4) , as shown in the example provided below.
The Firebase Assistant will open on the right side of the window.
Locate the Cloud Messaging folder, and select Set up Firebase Cloud Messaging , as shown below.
In the Firebase Notifications Assistant , select the Add FCM to your app (1) button as shown in the
following image.
A dialog will open indicating that new dependencies will be added via Gradle .
Select Accept Changes (2) to grant the changes.

NOTE
Unfortunately, the dependencies that are added automatically by the Gradle sync process (3 ) are incorrect and
will report failure!

To set up the dependencies correctly, replace the auto-added sentences with the following:
implementation 'com.google.firebase:firebase-core:16.0.3
implementation 'com.google.firebase:firebase-messaging:17.0.0
Once that process is complete:
Verify that the Firebase Notifications Assistant indicates that dependencies are now set up correctly (1) .

NOTE
In the beginning of this chapter, we acquired the necessary JAR files. Normally, the build file automatically fetches these
files.

To ensure that these JAR files are listed under the app/libs folder (2) , select all of the files and right-click
them.
Then choose Add as librar y... (3) , as shown in the example provided below.

Using the Android asset studio Notification icon generator, prepare the icons and place them inside
app/src/main/res .
In the example shown below, the icon is called ic_stat_blur_on .

Finally, select Rebuild Project .

Now we can start implementing code for receiving and handling notifications. We are going to modify (and
create if needed) 4 files:
1. app/src/main/AndroidManifest.xml
2. app/src/main/java/..packagePath../MainActivity.java
3. app/src/main/java/..packagePath../FooAppFirebaseInstanceIdSer vice.java
4. app/src/main/java/..packagePath../FooAppFirebaseMessagingSer vice.java
NOTE
The current implementation is crafted to be as short as possible, just to quickly test the notifications. Consider FCM
Guides for high-quality best practices and more complex implementation examples.

AndroidManifest.xml
In the following code, replace any MY_PACKAGE_IDENTIFIER placeholders with your own package identifier.

<?xml version="1.0" encoding="utf-8"?>


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="MY_PACKAGE_IDENTIFIER">
<uses-permission android:name="android.permission.INTERNET" />

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<!-- The following block enables our custom Firebase Instance ID Service-->
<service android:name=".FooAppFirebaseInstanceIdService" android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>

<service
android:name=".FooAppFirebaseMessagingService" android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>

</application>

</manifest>

MainActivity.java
The following placeholders in the code should be replaced according to your scenario.
PLAYFAB_TITLE_ID

Use the ID for your title that you received in PlayFab Game Manager.
PACKAGE_IDENTIFIER

Use the Java package identifier that matches your setup.


package PACKAGE_IDENTIFIER;

import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import com.playfab.PlayFabClientAPI;
import com.playfab.PlayFabClientModels.*;
import com.playfab.PlayFabErrors;
import com.playfab.PlayFabSettings;
import java.util.List;
import java.util.Map;

public class MainActivity extends AppCompatActivity {

// Invoked when activity is started


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

// Set PlayFab title


PlayFabSettings.TitleId = "PLAYFAB_TITLE_ID";

// Start login operation


AsyncTask.execute(new Runnable() {
@Override
public void run() {
if(login()) FooAppFirebaseInstanceIdService.setAllowRegisterForPush(true); // Ready to
register for push notifications
}
});
}

public boolean login(){


LoginWithAndroidDeviceIDRequest request = new LoginWithAndroidDeviceIDRequest();
request.CreateAccount = true;

// There are several approaches on getting unique android device id.


// https://stackoverflow.com/questions/2785485/is-there-a-unique-android-device-id
request.AndroidDeviceId = "qwerty";

PlayFabErrors.PlayFabResult<LoginResult> response =
PlayFabClientAPI.LoginWithAndroidDeviceID(request);
if(response.Error != null){
Log.d("Foo PlayFab App",CompileErrorsFromResult(response.Error));
return false;
}
return true;
}

// Utility method to compose an error message out of PlayFab result.


private static String CompileErrorsFromResult(PlayFabErrors.PlayFabError error) {
if (error == null)
return null;

String errorMessage = "";


if (error.errorMessage != null)
errorMessage += error.errorMessage;
if (error.errorDetails != null)
for (Map.Entry<String, List<String>> pair : error.errorDetails.entrySet())
for (String msg : pair.getValue())
errorMessage += "\n" + pair.getKey() + ": " + msg;
return errorMessage;
}
}
FooAppFirebaseInstanceIdService.java
The placeholder in the code displayed below should be replaced according to your scenario.
PACKAGE_IDENTIFIER
The Java package identifier that matches your setup.

package PACKAGE_IDENTIFIER;

import android.text.TextUtils;
import android.util.Log;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.FirebaseInstanceIdService;
import com.playfab.PlayFabClientAPI;
import com.playfab.PlayFabClientModels;
import com.playfab.PlayFabErrors;
import java.util.List;
import java.util.Map;

public class FooAppFirebaseInstanceIdService extends FirebaseInstanceIdService {

private static String _token;

private static boolean _allowRegistration;

// This is invoked from activity that performs authentication.


// Once login is complete this method is invoked.
// If we have a pending token, we use it to register for push notifications
public static void setAllowRegisterForPush(boolean isAllowed) {
_allowRegistration = isAllowed;
if (_allowRegistration && !TextUtils.isEmpty(_token)) {
registerForPush(_token);
}
}

// Invoked when firebase has fetched a token


// If we already have logged in, we use new token to register for push
@Override
public void onTokenRefresh() {
_token = FirebaseInstanceId.getInstance().getToken();
if (_allowRegistration && !TextUtils.isEmpty(_token)) {
registerForPush(_token);
}
}

private static void registerForPush(String token) {


PlayFabClientModels.AndroidDevicePushNotificationRegistrationRequest request = new
PlayFabClientModels.AndroidDevicePushNotificationRegistrationRequest();
request.DeviceToken = token;

PlayFabErrors.PlayFabResult<PlayFabClientModels.AndroidDevicePushNotificationRegistrationResult>
response = PlayFabClientAPI.AndroidDevicePushNotificationRegistration(request);

if (response.Error != null) {
Log.d("Foo PlayFab App", CompileErrorsFromResult(response.Error));
}
}

// Utility method to compose an error message out of PlayFab result.


private static String CompileErrorsFromResult(PlayFabErrors.PlayFabError error) {
if (error == null)
return null;

String errorMessage = "";


if (error.errorMessage != null)
errorMessage += error.errorMessage;
if (error.errorDetails != null)
for (Map.Entry<String, List<String>> pair : error.errorDetails.entrySet())
for (String msg : pair.getValue())
errorMessage += "\n" + pair.getKey() + ": " + msg;
return errorMessage;
}

FooAppFirebaseMessagingService.java
The placeholder in the code shown below should be replaced according to your scenario.
PACKAGE_IDENTIFIER
The Java package identifier that matches your setup.

package com.foo.playfab.app;

import android.util.Log;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;

public class FooAppFirebaseMessagingService extends FirebaseMessagingService {

@Override
public void onMessageReceived(RemoteMessage message) {
// Intercept the message here
Log.d("Foo PlayFab App","Message received: "+message.getNotification().getBody());
}
}

Testing
At this point, you should be able to deploy the application to the device.
Once you start the application, it will automatically log in and register for push notifications.
Select the Home button on your device to minimize the Application. This is important, as it allows us to
test the Notification that arrives into the system tray.
Next, go to your PlayFab title Game Manager page, and use the Dashboard to locate the latest Push
Registration .
Select the Player ID (1) .

This will open a Send Push Notification page for that player.
Select the Send Push Notification button (1) .
Type in the Title (2) .
Enter the body of your message (3) .
Commit your changes by selecting the Send Push Notification button (4) .

Verify that the message arrives in your device.

If your message arrives, messages are successfully being delivered into your application.
At this point you have successfully integrated. You may use the FooAppFirebaseMessagingSer vice to handle
the incoming message while your application is actually running.
Push notification templates
5/24/2022 • 4 minutes to read • Edit Online

Do you have a player base which prefers different languages? PlayFab simplifies localized push notifications by
allowing multiple languages to be stored against a single template ID. You provide the strings - and we’ll provide
the smarts to send the right localized versions to your players.

NOTE
Before we added support for push notification templates, developers were able to explicitly define their push notifications
inside the rules or scheduled tasks that triggered them. These will continue to behave as they have before - however, in
order to add additional languages, you must use templates.

This tutorial walks you through the steps required to create a basic localized push notification template, and
then discusses how to configure PlayFab to automatically send it, when one of your players meets the specified
criteria.

Requirements
This is an advanced tutorial. It focuses on how to create a push notification template with localized strings, and
then configure logic to trigger the sending of that template to your players.
Please make sure that all requirements have been met or you will not be able to complete this tutorial. This
tutorial assumes your title has already been configured to send push notifications.

NOTE
For an introduction to push notifications and instructions for how to enable them on your title, please refer to the Push
notifications quickstart. It includes pointers for both iOS and Android (including configuring advanced payloads), as well as
how to use Postman to validate behavior.

Please become familiar with how to leverage our title default language and preferred player language support
in the Setting Default Languages tutorial. You must have a title default language set to continue with push
notification templates.

Create a push notification template


For the purpose of this tutorial, we’ll create a basic push notification to send to lapsed players, in the hopes that
they return to our title.
In the PlayFab Game Manager:
1. Select the Content section.
2. Select the Push Notifications Templates tab.
3. Click the New Push Notification Template button.
4. Add a new language using the drop-down menu in the Language (Title default) field.
5. Choose the language you want to add to the template, and type in the localized strings as shown below.
Subject:
어서 돌아오세요

Message:

<Profile.DisplayName>, 보고싶습니다. 다시돌아오시면 서프라이즈 선물을 받으실수있도록 준비했습니다. 다시한번 오셔서


들러보시겠습니까!

The following example displays what it should look like.

Select the SAVE PUSH NOTIFICATION TEMPL ATE button and you’re ready to go!
Sending this template to players who prefer Korean will get the localized version of the notification, all other
players will receive your default language message in English.

Trigger push notifications via rules, tasks, and player segments


The next step for our scenario is to leverage PlayFab triggered actions to send push notifications when a player
meets our specified criteria. We want to entice players to return if they haven’t visited our game in over 30 days.
This kind of criteria makes using player segmentation logic a natural fit for our lapsed player scenario, but
please note that you can trigger these same kinds of actions on rules and scheduled tasks. Both of those are
under the Automation menu in Game Manager. You can also use CloudScript, or our APIs to send a push
notification.
Let’s continue with the player segmentation example. First, we’ll set up a player segment for lapsed players:
1. Select the Players area.
2. Choose the Segments tab, and New Segment .

NOTE
We’re defining “lapsed” as not logging into the game for over 30 days (43200 minutes).

If you were to select the SAVE SEGMENT button at this point, you’d be able to use this segment to identify and
analyze players who haven’t visited your title for a while. When a player goes from 29 days without logging in
to 30 days, PlayFab will automatically add that player to this Lapsed Players segment.
Then, if a lapsed player logs in again, PlayFab will automatically remove them from this segment. Let’s have
PlayFab send our push notification when a player enters this segment:
With the entered Segment tab selected, select ADD ACTION that appears just above the Save Segment
button.
Then go to the Type field, and use the drop-down menu to select Send push notification .
Go to the Push notification template field next to it, and select Lapsed Players template from the second
drop-down menu.
Below is an example of how your screen should appear.
Now, when a player enters the Lapsed Players segment, PlayFab will send your localized push notification to
them. That’s all it takes to configure your push notification going out to your players.
While we’re here, let’s quickly discuss how you might make good on the promise of the “Welcome Back”
goodies we mention in the notification itself. Configuring actions to fire when the player leaves the segment is
an easy way (but not the only way) to make sure the player gets the gift you promised.
For this game, we have a CloudScript function which triggers an in-game experience welcoming the player back,
so we want to execute that for the player and grant them a special item from our catalog.
Push notifications for Android
5/24/2022 • 5 minutes to read • Edit Online

Prerequisites
Push Notifications quickstart
Unity3D quickstart
[Optional] Unity Editor Extensions
[Optional] Postman Quickstart

Configuring the Android notification channel


NOTE
The Google and Firebase developer consoles experience changes regularly. The setup description in this section best
describes the values you need - and how to get them - as of June 2017.

Google and Firebase setup


There are three Google websites that you must use and synchronize. In Google/Firebase, there are both Projects
and Apps:
Project :
Ensure that your project is set up and accessible from the Google API Manager.
Import your project into the Firebase Console if it's not already there.
App :
Firebase Projects contain apps.
The Google Play Dev Console also contains apps.
Make sure your app exists in both locations, with the same name and identifier (for example, Unicorn
Battle and com.playfab.unicornbattle2).
PlayFab requires a server API key
You can get this key from the Google API Manager, or from the Firebase Console
Google API Manager :
Select your Project .
Select Credentials (left menu).
The Firebase Project import will have created a Ser verKey for you here.
Firebase Console :
Select your Project or App , and find the Settings option (there are many ways to do this, all of which
lead you to the same place).
In the General tab, this is listed as the Web API Key .
In the Cloud Messaging tab, this is listed as the Legacy ser ver key .
All of the keys described above should be identical, and they are all the API key described in this
document.
NOTE
If they are not identical, the Legacy ser ver key is the one needed by PlayFab.

Using the API key


Provide your API key in one of two ways:
1. Input your key directly into the Game Manager UI : Settings (for your Title ) > Push Notifications
> Android .
2. Or call SetupPushNotification using Postman or a Unity project with Server API methods enabled.
Name: your_game_name
Platform: GCM
Credential: (Google ser ver API Key ): AIza**ppo

Overwrite OldARN: true

You should receive an HTTP 200 OK response with data similar to the following.

// Postman JSON result output


{
"code": 200,
"status": "OK",
"data": { "ARN" : "arn:*******/GCM/your_game_name" }
}

Once set up properly (using either method), you should see this in the Game Manager UI Settings
(for your title) > Push Notifications > Android .

Getting started: push notifications for Android + Unity


To set up your Unity project:
Create a new Unity project.
[OPTIONAL] Import the PlayFab Unity Editor Extensions package.
Import the Unity PlayFab SDK package.
Follow the FCM Unity guide to install FCM messaging, and set up a project for push notifications.
Once finished, you can continue with this guide to receive messages from PlayFab.
We will give you a complete FCM-ready monoBehaviour script in the following example, which
combines FCM and PlayFab.
In the FCM guide, you created a monobehavior script that set up the Firebase plugin.
You can continue using that monobehavior script, or replace it with the one in the example that
follows.
Setting up your first Push Notification
In Unity, open the script you created in the FCM tutorial, and replace the contents.

using PlayFab;
using PlayFab.ClientModels;
using PlayFab.Json;
using UnityEngine;

public class MsgCatcher : MonoBehaviour


{
public string pushToken;
public string playFabId;
public string lastMsg;

// OnGUI should be deleted/replaced with your own gui - This is only provided for debugging
public void OnGUI()
{
GUI.Label(new Rect(0, 0, Screen.width, 200), pushToken);
GUI.Label(new Rect(0, 200, Screen.width, Screen.height - 200), lastMsg);
}

private void OnPfFail(PlayFabError error)


{
Debug.Log("PlayFab: api error: " + error.GenerateErrorReport());
}

public void Start()


{
// PlayFabSettings.TitleId = "TITLE_ID";
Firebase.Messaging.FirebaseMessaging.TokenReceived += OnTokenReceived;
Firebase.Messaging.FirebaseMessaging.MessageReceived += OnMessageReceived;
LoginToPlayFab();
}

private void LoginToPlayFab()


{
#if UNITY_ANDROID
var request = new LoginWithAndroidDeviceIDRequest { AndroidDeviceId =
SystemInfo.deviceUniqueIdentifier, CreateAccount = true, };
PlayFabClientAPI.LoginWithAndroidDeviceID(request, OnPfLogin, OnPfFail);
#endif
}

private void OnPfLogin(LoginResult result)


{
Debug.Log("PlayFab: login successful");
playFabId = result.PlayFabId;
RegisterForPush();
}

private void RegisterForPush()


{
if (string.IsNullOrEmpty(pushToken) || string.IsNullOrEmpty(playFabId))
return;
return;

#if UNITY_ANDROID
var request = new AndroidDevicePushNotificationRegistrationRequest {
DeviceToken = pushToken,
SendPushNotificationConfirmation = true,
ConfirmationMessage = "Push notifications registered successfully"
};
PlayFabClientAPI.AndroidDevicePushNotificationRegistration(request, OnPfAndroidReg, OnPfFail);
#endif
}

private void OnPfAndroidReg(AndroidDevicePushNotificationRegistrationResult result)


{
Debug.Log("PlayFab: Push Registration Successful");
}

private void OnTokenReceived(object sender, Firebase.Messaging.TokenReceivedEventArgs token)


{
Debug.Log("PlayFab: Received Registration Token: " + token.Token);
pushToken = token.Token;
RegisterForPush();
}

private void OnMessageReceived(object sender, Firebase.Messaging.MessageReceivedEventArgs e)


{
Debug.Log("PlayFab: Received a new message from: " + e.Message.From);
lastMsg = "";
if (e.Message.Data != null)
{
lastMsg += "DATA: " + JsonWrapper.SerializeObject(e.Message.Data) + "\n";
Debug.Log("PlayFab: Received a message with data:");
foreach (var pair in e.Message.Data)
Debug.Log("PlayFab data element: " + pair.Key + "," + pair.Value);
}
if (e.Message.Notification != null)
{
Debug.Log("PlayFab: Received a notification:");
lastMsg += "TITLE: " + e.Message.Notification.Title + "\n";
lastMsg += "BODY: " + e.Message.Notification.Body + "\n";
}
}
}

Build and run your Unity project on a device. If you receive a push notification with the text, Push notifications
registered successfully , then everything worked as expected.

NOTE
PlayFabSettings.TitleId = TITLE_ID . You must set your own TitleId . This example will not work if you don't
update this TitleId , because our title is registered with our Firebase Keys and settings, not yours. You can do so by un-
commenting this line and replacing TITLE_ID with your titleId , or you can choose your title from the optional Editor
Extensions plugin mentioned in the previous section.

Troubleshooting Android
Verify that you can send a test push notifications from the Firebase Console.
If you cannot, then your Firebase plugin is not set up correctly, and you should review the Firebase
Documentation to find out why, or contact Firebase Support.
Ensure your FCM client pushToken is set properly.
The OnTokenReceived function in the example should be called, and should have a valid token.
If it is not called, your Firebase plugin is not set up correctly, and you should review the Firebase
Documentation to find out why, or contact Firebase Support.
Ensure your titleId is set to a title that you own, and that it has been registered with the server API key
from your Firebase project.
Advanced Features
In ser ver.SendPushNotification , you can use request.Package .CustomData to deliver arbitrary data to the
device. In the example previously, this is delivered to the section with the following comment.

Debug.Log("PlayFab: Received a message with data:");

You can customize your client receiver to utilize that data however you like. CustomData is not displayed to the
player, so it can be used to deliver custom game information to your client, or to locally schedule another future
notification using the FCM plugin.
You can also use request.Package .CustomData or request AdvancedPlatformDeliver y to deliver to many
3rd party plugins.

NOTE
3rd party plugin delivery is not supported or guaranteed, but is available for advanced users.

Additional Support
For help, example bugs, and related questions, drop us a line in our Forums.
Currently, we only support our services for the standard flow described in this document. If you team is looking
for additional functionality with other common push services or plugins, please let us know! We love getting
feedback from our developer community.
For documentation on the push payload via Amazon SNS:
Amazon SNS Message & JSON Formats
Push notifications for iOS
5/24/2022 • 3 minutes to read • Edit Online

Prerequisites
This tutorial assumes that you are familiar with the concepts covered in our Push Notifications quickstart.

Configuring the Apple notification channel


1. Ensure you have an active iO development (APNS_SANDBOX) or production (APNS) certificate. If you do not,
create one from the Apple Developer Por tal under Cer tificates, Identities and Profiles .

2. Export the certificate of your choosing (development or production):


Begin by downloading a copy of your certificate from the Apple Developer Por tal under
Cer tificates, Identities and Profiles . This will create a .cer file.
Open and install the certificate into your Keychain Access .
View your installed certificate under the Cer tificates subcategory.
Export your Keychain Access Cer tificate to .p12 format.

Convert the .p12 file to a .pem file using the following console command:
openssl pkcs12 -in apns-dev-cert.p12 -out apns-dev-cert.pem -nodes -clcerts

Once you have the .pem file , you can upload it directly through the PlayFab Game Manager
under your Title's settings > Push Notifications .
Alternatively, use the generator below to craft a JSON request for SetupPushNotification .
JSON Request generator for SetupPushNotification
The request generator uses the following pieces of information to create a JSON Request:
Platform - Use one of the following values: APNS (iOS), APNS_SANDBOX (iOS), GCM (Android)
Application Name - Enter the name of the application sending the message.

NOTE
Application names must only be made up of uppercase and lowercase ASCII letters, numbers, underscores, hyphens, and
periods, and must be between 1 and 256 characters long. They must also be must be unique.

PEM Cer tificate / API Key - For iOS (APNS or APNS_SANDBOX), use the complete contents of your PEM
file.
Once the JSON is generated, use it to execute a call to SetupPushNotification . The response should look like the
example that follows.

{
“code” : 200,
“status” : “OK”,
“data” :
{
“ARN” : “arn:*******/GCM/your_game_name”
}
}

Congratulations! You have now configured your title’s iOS messaging channel.

Registering your iOS Client for push


For iOS, you must rely on the default behavior of how iOS handles push notifications, as PlayFab does not offer
a native implementation on Unity at this time.
By default, notifications received while the game is in the background will be routed to the Notification area.
Alternatively, notifications received while the game is the active app will be received silently, and will not be
visible in the Notification area.
The following code from the sample is run on client Start() .

// must be called before trying to obtain the push token


// an asynchronous call with no callback into native iOS code that takes a moment or two before
// the token is available. (so spin and wait, or call this one early on)
// this will always return null if your app is not signed
UnityEngine.iOS.NotificationServices.RegisterForNotifications(UnityEngine.iOS.NotificationType.Alert |
UnityEngine.iOS.NotificationType.Badge | UnityEngine.iOS.NotificationType.Sound, true);

At this point, if the user has opted in for notifications, we can call the PlayFab API
RegisterForIOSPushNotification.
byte[] token = UnityEngine.iOS.NotificationServices.deviceToken;
if(token != null)
{
RegisterForIOSPushNotificationRequest request = new RegisterForIOSPushNotificationRequest();
request.DeviceToken = System.BitConverter.ToString(token).Replace("-", "").ToLower();
PlayFabClientAPI.RegisterForIOSPushNotification(request, (RegisterForIOSPushNotificationResult result)
=>
{
Debug.Log("Push Registration Successful");
}, OnPlayFabError);
}
else
{
Debug.Log("Push Token was null!");
}

If no errors occurred, congratulations! Your iOS client has been successfully linked to your title’s Apple
Notification channel.

Troubleshooting iOS
Verify that you have valid .pem files.
Ensure that the same certificate used in SetupPushNotification is used by XCode to sign your App.
Verify that the Push Notification API is enabled for your build in XCode.
Verify that your signing certificate matches the PlayFab platform. When running SetupPushNotification ,
use OverwriteOldARN = true to rebind the channel to a new platform. Only one iOS environment (APNS or
APNS_SANDBOX) can be active on a title at a given time.

Additional Support
For help, example bugs, and related questions, drop us a line in our Forums.

NOTE
Currently, we only support our services for the standard flow described in this document. If your team is looking for
additional functionality with other common push services or plugins, please let us know! We love getting feedback from
our developer community.
Email Messaging
5/24/2022 • 2 minutes to read • Edit Online

With email messaging, you can send customized emails to players:


On a prearranged schedule.
Triggered by a PlayStream event rule.
Or by calling an API.
The content of the emails is fully customizable, with HTML templates that can include player profile properties.
The emails are sent from your own email server, so details such as the From and Reply to: fields are consistent
with your brand.
Using email messaging, you can send an email to:
Verify a user’s email address.
Reset their password.
Target a segment of lapsed players with a link to redeem a gift.
Notify active players of an upcoming special event.
These are just a few examples of addressing customer requests, or stimulating player engagement.
Email messaging quickstart
5/24/2022 • 2 minutes to read • Edit Online

To send emails from PlayFab, you will need to have your own external SMTP server with a username and
password. Once you have an SMTP server available, check out Setting up an SMTP server with add-ons to
configure your title to send emails.

NOTE
You can use Gmail as an SMTP server for testing - but with Gmail, you are limited to 2,000 emails per day.

Once your SMTP Server is set up and configured in PlayFab, you can follow our tutorials for Using a rule to
verify a contact email address or Using email templates
You can also use the following APIs to manage player contact information and email functionality:
AddorUpdateContactEmail - Updates or adds a contact email to the player’s profile.
RemoveContactEmail - Deletes a contact email from the player’s profile.
SendEmailFromTemplate - Sends a template email to a player’s primary contact email.
SendAccountRecoveryEmail - Sends an Account Recovery email to the specified player.
ResetPassword - Resets the player’s password for a given title.
GetPlayerIdFromAuthToken - Gets a player’s ID from an authorization token.
Emails Tutorials
5/24/2022 • 2 minutes to read • Edit Online

These tutorials show you how to work with e-mail.


Localized email templates
Setting up an SMTP server with add-ons
Using a rule to verify a contact email address
Using email templates
Localized email templates
5/24/2022 • 3 minutes to read • Edit Online

PlayFab is introducing support for storing localized strings on behalf of game developers. In addition, we are
adding the necessary logic to provide your players with the correct strings for the language they prefer.
This tutorial walks you through how to use localized email templates. With localized email templates, you can
make multiple translated versions of an email, and associate all of them with one template ID.

NOTE
Any templates introduced before this feature was released will retain their behavior. However, you can easily update them
to use the new localized format used by new email templates.

Requirements
This is an advanced tutorial. Please make sure that all requirements have been met, or you will not be able to
complete this tutorial.
For an introduction to email templates, refer to the Using Email Templates to Send an Account Recovery
Email tutorial.
Please review the information on how to work with default languages on your title, and the preferred
languages for your players in the Setting Default Languages tutorial. You must have a title default language
set to continue with localized email templates.

Updating an existing email template


The first thing we will do is update the existing account recovery email template we made in the Using Email
Templates to Send an Account Recovery Email tutorial mentioned above.
1. Select Content from the menu on the left.
2. Go to the Email Templates tab.
3. Move to the Template name field, and select the Account Recover y template.

For the purposes of this tutorial, we will assume your title default language is English. You’ll see that your
existing version of the template shows up as the default language version.

Adding more languages is as simple as selecting the + ADD L ANGUAGE link that is provided, then choosing
the language you want to add to the template, and typing in the localized strings.
In this example, we're going to add the following French strings to our existing template.
French email subject:

Réinitialisation du mot de passe demandée

French email body:

<head></head>
<body><p>Vous avez récemment demandé un mot de passe avec nous. </p>
<p>Cliquez <a href="$ConfirmationUrl$">ici</a> s'il vous plaît pour être dirigé vers une page pour
réinitialiser votre mot de passe.
Here's what it should look like:
When you select the SAVE EMAIL TEMPL ATE button, you'll be redirected back to the page containing the list
of your email templates.
As you can see, a new language version was added, but a new template was not added, since all language
versions are stored under the same template ID.

Sending localized emails


Next, we will send our new localized version of the email. As was mentioned in the Setting Default Languages
tutorial, PlayFab does the heavy lifting to match your title's supported languages with your players' preferred
language. All you need to do is tell us to send the email.
To verify this behavior, create two test players.
Leave one of the new players without a preferred language. This will demonstrate how PlayFab falls back to the
title's default if there is no language specified or if there is no match between the title's language and the player's
language.
Set the other new player's language by using Game Manager, or by using the SetProfileLanguage API. We have
used French in this example.

NOTE
When using the SetProfileLanguage API, the language string must be specified in the ISO 639-1 format (for example,
"en", "es", or "ja"). At the current time, the code "zh" is not supported.

Make sure you have set the contact email on both players as explained in Step 2 of the Using Email Templates to
Send an Account Recovery Email tutorial, before continuing on to the next step.
Use the SendCustomAccountRecoveryEmail API once per player to send this template:
Once in French to the player whose preferred language is French.
Once in the default language to a player with no preferred language set.
Sample email to the player with no preferred language is shown below.

Sample email to the player whose preferred language is French is shown below.
Conclusion
As you can see, PlayFab noticed there was a match between your template's support for French, and the player's
language preference.
Where there was no match or no preference, the player received your title's default language strings.
If you have any questions or feedback on this tutorial, please contact us through our forums or slack channel.
Setting up an SMTP server with add-ons
5/24/2022 • 2 minutes to read • Edit Online

This tutorial walks you through how to set up an SMTP add-on, to support sending custom emails through
PlayFab.

Requirements
Game Manager will be required, as the SMTP server for the title is set up using an add-on. Read our Game
Manager Quickstart if you are unfamiliar with it.

Go to the add-on page and install SMTP


In Game Manager :
1. Go to Add-ons .
2. Under the Marketing section, select the SMTP add-on. This will redirect you to the Add-on page.

3. Select the INSTALL SMTP button.

Configure SMTP
A form should appear with the Host name , Por t number , Username , and Password fields.
Fill out the form with Host name , Por t number , Username , and Password for your SMTP server.
Select the SAVE SETTINGS button, and the add-on should now be installed.

NOTE
If your SMTP server requires SSL/TLS, use por t 587 .

Testing
To test this feature, you can use the Gmail SMTP server, provided you have a Gmail account. To use Gmail, fill in
the fields as follows:
Host name: smtp.gmail.com
Port number: 587
Username: (your gmail address - e.g., "support@playfab.com")
Password: (your password )

NOTE
If you have 2-factor authentication enabled, you will need to create an App password. See Sign in using an App password
for more information.

The SMTP add-on is now installed, and will show a green check and message indicating success.
Using a rule to verify a contact email address
5/24/2022 • 6 minutes to read • Edit Online

This tutorial walks you through the steps for creating a rule that sends a verification email when a player
changes their contact email address.

Requirements
IMPORTANT
This is an advanced tutorial. Please make sure that all of the requirements have been met, or you will not be able to
complete this tutorial.

To send custom emails with email templates, you will need to have your own SMTP server with a username
and password. Please verify that you have your own SMTP server before following our tutorial Setting up an
SMTP server with add-ons.

NOTE
You can use Gmail for testing - but with Gmail you are limited to 2,000 emails per day.

Basic knowledge of how to create a player will be necessary, since there will need to be players with a
username and password before calling account recovery logic.
Read the Game Manager quickstart if you are unfamiliar with the Game Manager, as it is the place where
email templates are created.
Knowledge of how to work with player profiles will be required, to confirm that emails will be necessary for
checking that a contact email has been added to a player's profile. Please read up on how to get a player's
profile in the Getting Player Profiles tutorial, and make sure that under the Client Profile Options on your
Title you allow Contact email addresses .
Creating a rule will be necessary in this tutorial it is a good idea to read up on how Rules work.

Step 1 - Create an email template


The first thing we will do is create an account recovery email template.
Select Content from the menu on the left.
Go to the Email Templates tab.
Select the NEW EMAIL TEMPL ATE button.
Now add a New Email Template , filling in the fields as follows and leaving the Error Callback URL empty:
Template name : MyFirstEmailVerificationTemplate
Template type : Email Verification
Email subject : Verify your email
Email body : (enter as below)

<head></head>
<body><p> You recently registered a new email with us.</p>
<p>Please click <a href="$ConfirmationUrl$">here</a> confirm your email. Thanks!</p>

From Name : The name you want to show in the From field in the email.
From Email Address : The email address you want to show in the From field in the email. This must be
an email domain that the SMTP server enables you to send emails from.

NOTE
Some email servers, like Gmail, will ignore this field and send from the account set up with the SMTP server.

Callback URL : https://www.example.com


A few things to remember
The $ConfirmationUrl$ in the email body generates a customized URL that when selected, tracks that a user
has selected the URL, and then issues a redirect to the Callback URL . In this case, it is injected into an
anchor tag .
The Callback URL is the URL that PlayFab will redirect to after the player selects the Confirmation URL
link. It can be a static page that tells the user they were successful in confirming their email. In this case, we
will redirect to https://www.example.com.
After filling the form out, select the SAVE EMAIL TEMPL ATE button, and you will be redirected back to the
page containing the list of your email templates. Make a note of the ID of the email template as it will be used in
Step 4.
Step 2 - Create a rule to send an email when a contact email is
updated
Next, we will create a rule to send a verification email every time a player updates their contact email. In Game
Manager :
Select Automation in the menu to the left.
Select the Rules tab.
Select NEW RULE .
Fill out the Rule Name field with your Rule VerifyUpdatedEmail .
From the Event Type drop-down, select com.playfab.player_updated_contact_email .
Under the Actions heading, select +ADD ACTION .
Choose Send Email from the Type drop-down.
The Email template drop-down should be populated by the template created in Step 1
MyFirstEmailVerificationTemplate .
If it is not, select MyFirstEmailVerificationTemplate from the drop-down.
Step 3 - Add a contact email to a player
For this next step, you will need an existing player account.
We add a contact email to the player using AddOrUpdateContactEmail.

NOTE
A Contact Email field in a Player Profile is different from the Login Email field on a Player Profile, even though they
may both contain the same email address. Any time you send email to the player, it will only go to the contact email
address.

C# code example
In the following example, we log in a player, then add a contact email using AddOrUpdateContactEmail. Make
sure the email address associated with the player is one that you can access.
void AddContactEmailToPlayer()
{
var loginReq = new LoginWithCustomIDRequest
{
CustomId = "SomeCustomID", // replace with your own Custom ID
CreateAccount = true // otherwise this will create an account with that ID
};

var emailAddress = "testaddress@example.com"; // Set this to your own email

PlayFabClientAPI.LoginWithCustomID(loginReq, loginRes =>


{
Debug.Log("Successfully logged in player with PlayFabId: " + loginRes.PlayFabId);
AddOrUpdateContactEmail(loginRes.PlayFabId, emailAddress);
}, FailureCallback);
}

void AddOrUpdateContactEmail(string playFabId, string emailAddress)


{
var request = new AddOrUpdateContactEmailRequest
{
PlayFabId = playFabId,
EmailAddress = emailAddress
};
PlayFabClientAPI.AddOrUpdateContactEmail(request, result =>
{
Debug.Log("The player's account has been updated with a contact email");
}, FailureCallback);
}

void FailureCallback(PlayFabError error)


{
Debug.LogWarning("Something went wrong with your API call. Here's some debug information:");
Debug.LogError(error.GenerateErrorReport());
}

Step 4 - Confirm that the contact email was added to the player's
profile
Next, confirm that the contact email was added to the player's profile. Log into the Game Manager , and visit
the Players Profile page.
You should see a Contact Email listed for that player, with Verification Status : Pending .

NOTE
The Verification Status could be Unverified , if the verification email was not sent out yet, but will move to the
Pending state as soon as the email is sent.
You can also make a call to GetPlayerProfile with ShowContactEmailAddresses in the
PlayerProfileViewConstraints set as True to show that the player now has the contact email that we just added.

Step 5 - Check that the email was sent


Finally, we can check that the account recovery email was sent.
The first thing you can do is to go to the player's PlayStream in Game Manager :
Select Players in the menu to the left.
On the Players Tab, go to the PlayStream area.
It should show a Sent Email Event .

Selecting the Info icon on the Event should show JSON similar to the one shown below.
{
"EventName": "sent_email",
"EventNamespace": "com.playfab",
"Source": "PlayFab",
"EntityType": "player",
"TitleId": "YourTitleId",
"EventId": "a05625e48b1f4194bd08d1ff6a889cf8",
"EntityId": "64647AA368D6448E",
"SourceType": "BackEnd",
"Timestamp": "2017-10-27T09:35:16.2946918Z",
"History": null,
"CustomTags": null,
"Reserved": null,
"emailTemplateId": "7D6438687903D4DC",
"emailTemplateName": "MyFirstEmailVerificationTemplate",
"emailTemplateType": "EmailVerification",
"success": true,
"emailName": "Primary"
}

To verify that you actually received the email, go to the email of the player you created in Step 3. There should be
an email that looks similar to the one shown below.

If you inspect the URL in that email, you will see that it looks something like this one.

https://a5f3.playfabapi.com/EmailConfirmation/Confirm/?
token=2346241B7C277796&titleId=A5F3&templateId=38017AAE7F494AB3

When the player selects that URL, three things happen:


1. PlayFab generates a new PlayStream event, called auth_token_validated . This is how you know that the
player selected that URL in the email.
You can use that event to trigger actions, like granting coins or items to the player.
2. Because this email template was the special Email Verification template, PlayFab will then mark the player
email as Verified.
3. PlayFab will return a redirect URL sending the player to the callback URL website.
On this website you can show a static Thanks for verifying your email message, or something
more elaborate. The redirect URL will look something like this: https://www.example.com/?
token=2346241B7C277796.
Go ahead and select the URL found in the email.
You will be taken to the example.com website.
View your Player Profile using the Game Manager .
You will see that the Verification status has changed.

Conclusion
So that's it for this tutorial. You've seen how to setup your SMTP server, create an email template, and create a
rule that sends an email to a player verifying their email address.
If you have any questions or feedback on this tutorial, please let us know in our community forums.
Using email templates to send an account recovery
email
5/24/2022 • 7 minutes to read • Edit Online

This tutorial walks you through how to use the email template feature of PlayFab to send an account recovery
player's contact email address, to let a player reset their password.

Requirements
IMPORTANT
This is an advanced tutorial. Please make sure that all requirements have been met, or you will not be able to complete
this tutorial.

To send custom emails with email templates, you will need to have your own SMTP server with a username
and password. Please be sure that you have your own SMTP server before using our tutorial Setting up an
SMTP server with add-ons.

NOTE
You can use Gmail for testing, but Gmail limits you to 2,000 emails per day.

Basic knowledge of how to create a player will be necessary, since there will need to be players with a
usernames and passwords before calling account recovery logic.
Read the Game Manager quickstart if you are unfamiliar with the Game Manager, as it is the place where
email templates are created.
Knowledge of how to work with player profiles will be required to confirm that emails will be necessary for
checking that a contact email has been added to a player's profile. Please read up on how to get a player
profile in the Getting Player Profiles tutorial, and make sure that under the Client Profile Options on your
Title you allow Contact email addresses .

Step 1 - Create an email template


The first thing we will do is create an account recovery email template.
Go to Content .
Select the Email Templates tab.
Select the NEW EMAIL TEMPL ATE button.
Now add a New Email Template , filling in the fields as follows leaving the Error callback URL empty:
Template name : PasswordRecoveryTemplate
Template type : Account Recovery
Email subject : Password reset requested
Email body : (enter as below)

<head></head>
<body><p> You recently requested a password reset with us.</p>
<p>Please click <a href='$ConfirmationUrl$'>here</a> to be directed to a page to reset your password.
Thanks!</p>

From Name : The name you want to show in the From field in the email.
From Email Address : The email address you want to show in the From field in the email. This must be an
email domain that the SMTP server enables you to send emails from.

NOTE
Some email servers, like Gmail, will ignore this field and will send from the account set up with the SMTP server.

Callback URL : A callback URL to a password recovery form. At the minimum, the form must contain a
Password field for the player to enter a new password.
A few things to note
The $ConfirmationUrl$ in the email body generates a customized URL that, when selected, tracks that a user
has chosen the URL, and then issues a redirect to the Callback URL . In this case, it is injected into an anchor
tag.
The Callback URL is the URL that PlayFab will redirect to after the player selects the confirmation URL link.
It will need to be a hosted web form that contains at very minimum a Password field, in order to make a
ResetPassword API call later in this tutorial.
After filling the form out, select the SAVE EMAIL TEMPL ATE button, and you will be redirected back to the
page containing the list of your Email Templates showing. Make a note of the ID of the Email Template as it
will be used in Step 4.
Step 2 - Add username, password, login email, and contact email to a
player
For this next step, you will need an existing player account.
We will add a username, password, and login email using AddUsernamePassword. Additionally, we add a
contact email to the player using AddOrUpdateContactEmail.

NOTE
A contact email field on a player profile is different from the login email field on a player profile, even though they may
both contain the same email address. Any time you send email to the player, it will go to the contact email address.

C# code example
In the following example, we log in a player, then add a username, password, and login email using
AddUsernamePassword. We then add a contact email using AddOrUpdateContactEmail. Make sure the email
address associated with the player is one that you can access.
void CreatePlayer()
{
var loginReq = new LoginWithCustomIDRequest
{
CustomId = "SomeCustomID", // replace with your own Custom ID
CreateAccount = true // otherwise this will create an account with that ID
};

var username = "yourusername"; // Set this to your username


var password = "yourpassword"; // Set this to your password
var emailAddress = "testaddress@example.com"; // Set this to your own email

PlayFabClientAPI.LoginWithCustomID(loginReq, loginRes =>


{
Debug.Log("Successfully logged in player with PlayFabId: " + loginRes.PlayFabId);
AddUserNamePassword(username, password, emailAddress); // Add a username and password
AddOrUpdateContactEmail(loginRes.PlayFabId, emailAddress);
}, FailureCallback);
}

void AddUserNamePassword()
{
var request = new AddUsernamePasswordRequest
{
Username = "yourusername",
Password = "yourpassword",
Email = "exampleemail@emaple.com" // Login email
};
PlayFabClientAPI.AddUsernamePassword(request, result =>
{
Debug.Log("The player's account now has username and password");
}, FailureCallback);
}

void AddOrUpdateContactEmail(string playFabId, string emailAddress)


{
var request = new AddOrUpdateContactEmailRequest
{
PlayFabId = playFabId,
EmailAddress = emailAddress
};
PlayFabClientAPI.AddOrUpdateContactEmail(request, result =>
{
Debug.Log("The player's account has been updated with a contact email");
}, FailureCallback);
}

void FailureCallback(PlayFabError error)


{
Debug.LogWarning("Something went wrong with your API call. Here's some debug information:");
Debug.LogError(error.GenerateErrorReport());
}

Step 3 - Confirm that the contact email was added to the player's
profile
Next, confirm that the contact email was added to the player's profile. Log into the Game Manager , and visit
the Player's Profile page. You should see a Contact email listed for that player.
You can also make a call to GetPlayerProfile with ShowContactEmailAddresses in the
PlayerProfileViewConstraints set as true, to show that the player now has the contact email that we just added.

Step 4 - Send an account recovery template email


Now we will send the verification email using SendEmailFromTemplate using the email template ID in Step 1
to the Player we created in Step 2.
C# Code Example
In the following example, we send an account recovery email using SendCustomAccountRecoveryEmail.

void SendCustomAccountRecoveryEmail(string emailAddress, string emailTemplateId)


{
var request = new SendCustomAccountRecoveryEmailRequest
{
Email = emailAddress,
EmailTemplateId = emailTemplateId
};

PlayFabServerAPI.SendCustomAccountRecoveryEmail(request, res =>


{
Debug.Log("An account recovery email has been sent to the player's email address.");
}, FailureCallback);
}

void FailureCallback(PlayFabError error)


{
Debug.LogWarning("Something went wrong with your API call. Here's some debug information:");
Debug.LogError(error.GenerateErrorReport());
}

Step 5 - Check that the email was sent


Finally, we can check that the account recovery email was sent.
The first thing you can do is go to the player's PlayStream area. In Game Manager :
Select Player from the menu on the left.
Go to the PlayStream area of the screen.
It should display a Sent Email Event .

Selecting the Info icon on the event should show JSON similar to what appears below.

{
"EventName": "sent_email",
"EventNamespace": "com.playfab",
"Source": "PlayFab",
"EntityType": "player",
"TitleId": "YourTitleId",
"EventId": "655f14ac45b341b59c217dcf04d26ef9",
"EntityId": "64647AA368D6448E",
"SourceType": "BackEnd",
"Timestamp": "2017-10-27T23:53:58.8717009Z",
"History": null,
"CustomTags": null,
"Reserved": null,
"emailTemplateId": "DC3E1B28881C6071",
"emailTemplateName": "PasswordRecoveryTemplate",
"emailTemplateType": "AccountRecovery",
"success": true,
"emailName": "Primary"
}

To check that you actually receive the email, go to the email of the player you created in Step 2. There should be
an email that looks similar to what is shown below.
If you inspect the URL in that email, you will see that it looks something like this example.

https://a5f3.playfabapi.com/EmailConfirmation/Confirm/?
token=2346241B7C277796&titleId=A5F3&templateId=38017AAE7F494AB3

When the player selects that URL, three things happen:


1. PlayFab generates a new PlayStream event called auth_token_validated . This is how you know that the
player selected that URL in the email. You can use that event to trigger actions, like granting coins or items to
the player.
2. PlayFab will return a redirect URL, sending the player to the callback URL. In this case, it should be a website
for the game with a form for the player to enter a new password.
3. The redirect URL will contain a token in the query string, and will look something like what appears below.
https://www.example.com/?token=2346241B7C277796.

Step 6 - Reset the player's password


After the player is directed to the callback URL and fills out the form with a new password, you can use that
information, in addition to the token in the query string, to issue a ResetPassword call.
C# code example
In the following example, we reset a player's password, based on a token and the new password the player
specifies in a form using ResetPassword.

void ResetPassword(string newPassword, string token)


{
var request = new ResetPasswordRequest
{
Password = newPassword,
Token = token
};

PlayFabAdminAPI.ResetPassword(request, result =>


{
Debug.Log("The player's password has been resetl");
}, FailureCallback);

void FailureCallback(PlayFabError error)


{
Debug.LogWarning("Something went wrong with your API call. Here's some debug information:");
Debug.LogError(error.GenerateErrorReport());
}
Step 7 - Check that the password was reset
Finally, verify that the player has reset their password successfully by logging in with LoginWithPlayFab.
C# Code Example
In the following C# example, we log in using LoginWithPlayFab and the new password the player reset to in
Step 6.

void LoginWithPlayFab(string username, string password)


{
var request = new LoginWithPlayFabRequest
{
Username = username,
Password = password
};

PlayFabClientAPI.LoginWithPlayFab(request, result =>


{
Debug.Log("Successfully logged in player with ID " + result.PlayFabId);
}, FailureCallback);
}

void FailureCallback(PlayFabError error)


{
Debug.LogWarning("Something went wrong with your API call. Here's some debug information:");
Debug.LogError(error.GenerateErrorReport());
}

Conclusion
That's it for this tutorial! You've seen how to set up your SMTP server, create an email template, send an account
recovery email, and reset a player's password.
If you have any questions or feedback on this tutorial, please let us know in our community forums.
What is PlayFab Data?
5/24/2022 • 2 minutes to read • Edit Online

PlayFab Data is a set of tools for data analytics, storage, processing, and exports. The features are Title data,
Players data, Characters data, Groups data, along with data management and provisiong features like Entities,
Content delivery network and Webhooks.
Players data, Characters data, Groups data are saved which manage the store settings, game save state, or other
data. To get started, see the Player data Quickstart.
Title data manages the remote configurations of the game as key-value pairs. To get started, see the Title data
Quickstart.
Entities are the most basic addressable "things" that PlayFab APIs operate on. Each entity has a Type and an Id
which together uniquely identify it. The parent/child relationships between entities exists which governs the
permissions on how an entity's resources may be accessed by other entities. To get started, see the Entities
Quickstart.
Content delivery network is an infrastructure used to deliver assets - such as images, audio, binary content, etc. -
to the end user that focuses on speed and availability. To get started, see the Content delivery network
Quickstart.
Webhooks enables you to do event handling in your own custom server. To get started, see the Webhooks
Overview.
Player Data
5/24/2022 • 2 minutes to read • Edit Online

Player data is information about a player that is stored to the PlayFab service that you can share across multiple
devices and multiple games.
PlayFab provides two ways to store player data:
Entities: Allows you to store data in objects and files across Players, Characters, and Groups.
Player Data/UserData: Allows you to store Key/Value pair data for players.
To provide the most flexibility and best performance, we recommended that all new titles use Entity objects.
In the PlayFab APIs, the function names use the term UserData . In the Game Manager , this concept is
described as Player Data . They are identical, and interchangeable.
There are three modes of access to player data:
Client: This is player data that is available to your title client to read and update. You use the client APIs
UpdateUserData to create, update, or delete and GetUserData to read data for the player.
Read Only: This is player data that is created or updated by your server. Your title client can read, but not
update, this data. You use the server API UpdateUserReadOnlyData to create, update, or delete and the client
API GetUserReadOnlyData to read title-specific data for the player. This data is visible to the player, but can
only be modified by the server.
Internal: This is player data that is only available to your server. You use the server APIs
UpdateUserInternalData to create, update, or delete and GetUserInternalData to read title-specific data for the
player. This data is server-only, and cannot be seen by the client.
When you use player data, only User Data and User Read Only Data are available to the Client API. If you have
player data that another player should be able to read, you need to set the Permission value to Public when
you write the data.

Player data vs player publisher data


Player data is player information that is specific to a game title. It should be used for title-specific information -
such as saving your player's position in a dungeon, or other game-specific data.
Player Publisher data is data associated with the player account, as opposed to the player account plus the title.
It is used to save information about a player relevant to all titles in your studio (which may also contain title-
specific information, for purposes of cross-title rewards).
All titles within a studio in PlayFab share a Publisher ID by default, and that ID defines this relationship. Player
accounts exist at the Publisher layer, and are shared across all titles with the same Publisher ID (and then
additionally have distinct player data per title).
If you need to have titles in a studio that have different Publisher IDs, or titles in different studios that share the
same Publisher ID, you can open a ticket in the PlayFab community forums and our Developer Success team
will help you out.
NOTE
Please don't confuse player Publisher data with Publisher data which is Key/Value Pair data shared by all titles (it is not
per-player).

Player Publisher data usage is nearly identical to player data usage. They are both dictionaries mapping a string
to a JSON blob (or other arbitrary string value).
For more information, see How to use player publisher data to grant a reward for playing multiple titles.
Quickstart: Set and get player data
5/24/2022 • 4 minutes to read • Edit Online

NOTE
In the PlayFab APIs, the function names utilize the term UserData . In the Game Manager , this concept is described as
Player Data . They are identical, and interchangeable.

Get started using PlayFab Player Data. This quickstart shows you how to set and retrieve player data using C# in
Unity and using PlayFab CloudScript.
Player data is information that applies to an individual player or player group (shared data) and is stored as
Key/Value Pairs (KVPs) by PlayFab. This topic covers client API calls, which are safe to call from any process or
context. It also covers server API calls, which should only be made from a dedicated server process you control,
or a carefully secured CloudScript call. Server APIs require your dev secret key, which you should never provide-
to or publish-with your client.
The C# Samples in this topic are written for the Unity SDK. The Unity SDK uses an event driven model to handle
non-synchronous tasks. To run the sample code using the standard C# or Xamarin C# SDKs you must modify
the code to use an async Task model. Methods that must be modified have Async append to the method name in
the signature. For example, SetObject in the Unity SDK becomes SetObjectAsync in the standard C# SDK. For
more information, see Asynchronous programming with async and await.

Requirements
A PlayFab developer account.
An installed copy of the Unity Editor. To install Unity for personal use via Unity Hub, or Unity+ for
professional use, see Download Unity.

NOTE
The PlayFab Unity3D SDK supports Unity Editor version 5.3 (released December 2015) and higher.

A Unity Project - this can be any of the following:


A brand new project. For more information, see Starting Unity for the first time.
A guided tutorial project. For more information, see Getting Started with Unity.
An existing project.
The PlayFab Unity3D SDK.
For information about setting up a PlayFab account and using PlayFab Game Manager, see Getting started for
developers.
For information about setting up the PlayFab Unity3D SDK, see Quickstart: PlayFab Client library for C# in Unity
topic which ensures you have a PlayFab account and have configured the Unity3D SDK.

About the code examples


The C# Samples in this topic are written for the Unity SDK. The Unity SDK uses an event driven model to handle
non-synchronous tasks. To run the sample code using the standard C# or Xamarin C# SDKs you must modify
the code to use an async Task model. Methods that must be modified have Async append to the method name in
the signature. For example, SetObject in the Unity SDK becomes SetObjectAsync in the standard C# SDK. For
more information, see Asynchronous programming with async and await.
While you can use an existing using Unity Project, the procedures in this quickstart assume that you are using
the sample that you create when you complete the Quickstart: PlayFab Client library for C# in Unity.

Player data in Game Manager


You can always get and set player data through Game Manager by performing the following steps.
Open Game Manager . If you are unfamiliar with it, see the Game Manager quickstart.
Select the Players tab.
Select the name of the Player . This will put you into the Players Account tab.
Select the Player Data tab to see their data.

Add a methods to set the player data and retrieve the player data
1. In the Unity Editor, open your sample project.
2. In the Project window, open Assets > Scripts and then open the PlayFabLogin script.
3. In Visual Studio, add the following to the following using statement:
using System.Collections.Generic;

4. To set player data, add a SetUserData method to the PlayFabLogin class. SetUserData uses the
UpdateUserData method to create or update the player data for the logged in player.
The method creates (or updates, if the Key Value Pairs (KVPS) already exist) the KVPs Ancestor with the
value Arthur , and Successor with the value Fred .

void SetUserData() {
PlayFabClientAPI.UpdateUserData(new UpdateUserDataRequest() {
Data = new Dictionary<string, string>() {
{"Ancestor", "Arthur"},
{"Successor", "Fred"}
}
},
result => Debug.Log("Successfully updated user data"),
error => {
Debug.Log("Got error setting user data Ancestor to Arthur");
Debug.Log(error.GenerateErrorReport());
});
}

5. To get player data, add a GetUserData method to the PlayFabLogin class. SetUserData uses the
GetUserData method to retrieved the player data for the specified player.
void GetUserData(string myPlayFabeId) {
PlayFabClientAPI.GetUserData(new GetUserDataRequest() {
PlayFabId = myPlayFabeId,
Keys = null
}, result => {
Debug.Log("Got user data:");
if (result.Data == null || !result.Data.ContainsKey("Ancestor")) Debug.Log("No Ancestor");
else Debug.Log("Ancestor: "+result.Data["Ancestor"].Value);
}, (error) => {
Debug.Log("Got error retrieving user data:");
Debug.Log(error.GenerateErrorReport());
});
}

6. To call the add calls to the SetUserData and GetUserData in the OnLoginSuccess medthod:

private void OnLoginSuccess(LoginResult result) {


Debug.Log("Congratulations, you made your first successful API call!");
SetUserData();
GetUserData(result.PlayFabId);
}

7. Save the file.

Run the sample


In the Unity Editor, select the play button. On success, the results of the of calls display in the console window.

See Also
How to set internal player data
How to get internal player data
How to set read-only player data
How to get read-only player data
How to modify read-only or internal player data from CloudScript
Title Data quickstart
Using Publisher Data
CloudScript quickstart
How to set internal player data
5/24/2022 • 2 minutes to read • Edit Online

To set internal player data, use the Server API UpdateUserInternalData method. This is data that the client cannot
access.
The C# Sample in this topic are written for the Unity SDK. The Unity SDK uses an event driven model to handle
non-synchronous tasks. To run the sample code using the standard C# or Xamarin C# SDKs you must modify
the code to use an async Task model. Methods that must be modified have Async append to the method name in
the signature. For example, SetObject in the Unity SDK becomes SetObjectAsync in the standard C# SDK. For
more information, see Asynchronous programming with async and await.

C# code example
The following C# code example uses the PlayFab server API to create (or update, if a key value already exists)
the KVPs with the key named Class , with the value Fighter , and Race with the value Human .

public void UpdateUserInternalData() {


PlayFabServerAPI.UpdateUserInternalData(new UpdateUserInternalDataRequest() {
PlayFabId = "user PlayFabId here - obtained from any successful LoginResult",
Data = new Dictionary<string, string>() {
{"Class", "Fighter"},
{"Race", "Human"},
},
},
result => Debug.Log("Set internal user data successful"),
error => {
Debug.Log("Got error updating internal user data:");
Debug.Log(error.GenerateErrorReport());
});
}

See also
How to get internal player data
How to get internal player data
5/24/2022 • 2 minutes to read • Edit Online

To get internal player data, use the Server API GetUserInternalData method. This is internal data that you should
not expose it to the client.
The C# Sample in this topic are written for the Unity SDK. The Unity SDK uses an event driven model to handle
non-synchronous tasks. To run the sample code using the standard C# or Xamarin C# SDKs you must modify
the code to use an async Task model. Methods that must be modified have Async append to the method name in
the signature. For example, SetObject in the Unity SDK becomes SetObjectAsync in the standard C# SDK. For
more information, see Asynchronous programming with async and await.

C# code example
The following C# code example retrieves the Key Value Pairs of the player internal data.

public void GetUserInternalData() {


PlayFabServerAPI.GetUserInternalData(new GetUserDataRequest() {
PlayFabId = "user PlayFabId here - obtained from any successful LoginResult",
},
result => {
if(result.Data == null || !result.Data.ContainsKey("Class")) Debug.Log("No Class");
else Debug.Log("Class: " + result.Data["Class"].Value);
},
error => {
Debug.Log("Got error getting internal user data:");
Debug.Log(error.GenerateErrorReport());
});
}

See also
How to set internal player data
How to set read-only player data
5/24/2022 • 2 minutes to read • Edit Online

To set read-only KVPs, you must call the Server API UpdateUserReadOnlyData method from a server process.
This is data that the server can modify, but the client can only read.
The C# Samples in this topic are written for the Unity SDK. The Unity SDK uses an event driven model to handle
non-synchronous tasks. To run the sample code using the standard C# or Xamarin C# SDKs you must modify
the code to use an async Task model. Methods that must be modified have Async append to the method name in
the signature. For example, SetObject in the Unity SDK becomes SetObjectAsync in the standard C# SDK. For
more information, see Asynchronous programming with async and await.

C# code example
The following C# code example uses the PlayFab server API to create (or update, if the KVPs already exist) the
KVPs with the key named Father , with the value Fred , Mother with the value Alice , Sister with the value
Lucy , and Brother with the value Doug .

public void UpdateUserReadOnlyData() {


PlayFabServerAPI.UpdateUserReadOnlyData(new UpdateUserDataRequest() {
PlayFabId = "user PlayFabId here - obtained from any successful LoginResult",
Data = new Dictionary<string, string>() {
{"Father", "Fred"},
{"Mother", "Alice"},
{"Sister", "Lucy"},
{"Brother", "Doug"}
},
Permission = UserDataPermission.Public
},
result => Debug.Log("Set read-only user data successful"),
error => {
Debug.Log("Got error updating read-only user data:");
Debug.Log(error.GenerateErrorReport());
});
}

See also
How to get read-only player data
How to get read-only player data
5/24/2022 • 2 minutes to read • Edit Online

To get read-only player data, use the Server API GetUserReadOnlyData method.
The C# Sample in this topic are written for the Unity SDK. The Unity SDK uses an event driven model to handle
non-synchronous tasks. To run the sample code using the standard C# or Xamarin C# SDKs you must modify
the code to use an async Task model. Methods that must be modified have Async append to the method name in
the signature. For example, SetObject in the Unity SDK becomes SetObjectAsync in the standard C# SDK. For
more information, see Asynchronous programming with async and await.

C# code example
The following C# code example uses the PlayFab server API to get all of the player read-only data.

public void GetUserReadOnlyData()


{
PlayFabServerAPI.GetUserReadOnlyData(new GetUserDataRequest()
{
PlayFabId = "user PlayFabId here - obtained from any successful LoginResult",
},
result => {
if(result.Data == null || !result.Data.ContainsKey("Sister")) Debug.Log("No Sister");
else Debug.Log("Sister: "+result.Data["Sister"].Value);
},
error => {
Debug.Log("Got error getting read-only user data:");
Debug.Log(error.GenerateErrorReport());
});
}

See also
How to set read-only player data
How to modify read-only or internal player data
from CloudScript
5/24/2022 • 2 minutes to read • Edit Online

Player data is accessible from CloudScript if you require it for your title.
For more information about using CloudScript, see CloudScript quickstart.
The C# Sample in this topic are written for the Unity SDK. The Unity SDK uses an event driven model to handle
non-synchronous tasks. To run the sample code using the standard C# or Xamarin C# SDKs you must modify
the code to use an async Task model. Methods that must be modified have Async append to the method name in
the signature. For example, SetObject in the Unity SDK becomes SetObjectAsync in the standard C# SDK. For
more information, see Asynchronous programming with async and await.

CloudScript code example


You must be very careful to ensure the security of your server API calls in CloudScript. The following code
demonstrates modifying a piece of read-only player data from CloudScript safely.

function IncrementReadOnlyUserData(args) {
var playerData = server.GetUserInternalData({
PlayFabId: currentPlayerId,
Keys: ["ReadOnlyTest"]
});

var prevCount = "0";


var nextCount = "1";
try {
prevCount = playerData.Data["ReadOnlyTest"].Value;
var prevInt = parseInt(prevCount, 10);
if (prevInt != prevInt) {
prevInt = 0;
nextCount = (prevInt + 1).toString();
}
} catch (e) {
prevCount = "0";
nextCount = "0";
}

var updateUserDataResult = server.UpdateUserInternalData({


PlayFabId: currentPlayerId,
Data:
{
"ReadOnlyTest": nextCount
}
});
}

C# code example
As explained in the CloudScript quickstart, you can call the following logic from the client.
public void CloudIncrement() {
PlayFabClientAPI.ExecuteCloudScript( new ExecuteCloudScriptRequest {
FunctionName = "IncrementReadOnlyUserData"
},
result => Debug.Log("CloudScript call successful"),
error => {
Debug.Log("CloudScript call failed");
Debug.Log(error.GenerateErrorReport());
});
}
How to use player publisher data to grant a reward
for playing multiple titles
5/24/2022 • 3 minutes to read • Edit Online

Rewards usually involve other systems outside of player data, so this example demonstrates awarding virtual
currency for the sake of simplicity.

Requirements
A PlayFab developer account.
A player must sign into both titles using the same credentials. One approach is to use Recoverable
Credentials , as described in our Login Basics and Best Practices tutorial. To add a Recoverable login to an
anonymous account, see our Account Linking tutorial.
This example requires a working knowledge of CloudScript:
Our example demonstrates basic data security to avoid player cheating. One could likewise use the
server API on a custom game server, if the title makes use of them.
Rewards triggered through PlayFab require usage of the appropriate PlayFab features. PlayFab Rewards can
be in the form of Vir tual Currency , Inventor y Items , Custom Player Data , Statistics , etc. Distributing
rewards outside of PlayFab systems is an advanced topic, and is not covered in this tutorial.
We also recommended that developers use good error handling on all server API calls made from CloudScript.

Each game reports a login to publisher data


Each game needs to report that a login occurred. For simplicity, our example only provides one reward for each
title, for each other publisher title played.
Feel free to expand on the idea with counters, timestamps, or other mechanisms to provide progressive or
sequential rewards.
The following CloudScript would need to be present in every game in your studio.
// CloudScript/Javascript

var PUBLISHER_USED_TITLES_KEY = "playedTitleIds";


handlers.TrackTitleUsage = function () {
// Get the User Publisher Data for this player, and convert it into our expected format
var getRequest = { Keys: [PUBLISHER_USED_TITLES_KEY], PlayFabId: currentPlayerId };
var getResult = server.GetUserPublisherInternalData(getRequest);
var playedTitlesList = JSON.parse(getResult.Data[PUBLISHER_USED_TITLES_KEY].Value); // format is
arbitrary, but this example assumes Array<string>
if (!playedTitlesList)
playedTitlesList = [];
// Check if we've played this title already
var alreadyPlayed = false;
for (var i = 0; i < playedTitlesList.length; i++)
alreadyPlayed = alreadyPlayed || playedTitlesList[i] === script.titleId;
if (alreadyPlayed)
return; // Nothing to do
// Update the list of played titles, and re-save
playedTitlesList.push(script.titleId);
var setRequest = { PlayFabId: currentPlayerId, Data: { PUBLISHER_USED_TITLES_KEY:
JSON.stringify(playedTitlesList) } };
server.UpdateUserPublisherInternalData(setRequest);
}

In particular, this example demonstrates using:


server.GetUserPublisherInternalData
server.UpdateUserPublisherInternalData.

Each game checks for redeemable rewards


After you are tracking which titles are played, you need to track and grant the rewards. This CloudScript function
will check for and grant available rewards, based on having played other titles.
// CloudScript/Javascript

var PUBLISHER_REDEEMED_TITLES_KEY = "redeemedTitleIds";


var MY_CROSS_TITLE_REWARDS = { "AU": 10 };
handlers.CheckCrossTitleRewards = function () {
// Get the publisher data concerning cross-title rewards for this player
var getRequest = { Keys: [PUBLISHER_USED_TITLES_KEY, PUBLISHER_REDEEMED_TITLES_KEY], PlayFabId:
currentPlayerId };
var getResult = server.GetUserPublisherInternalData(getRequest);
var redeemedTitleRewards = JSON.parse(getResult.Data[PUBLISHER_REDEEMED_TITLES_KEY].Value); // format is
arbitrary, but this example assumes { [key: string]: Array<string> }
if (!redeemedTitleRewards)
redeemedTitleRewards = {};
var playedTitlesList = JSON.parse(getResult.Data[PUBLISHER_USED_TITLES_KEY].Value); // format is
arbitrary, but this example assumes Array<string>
if (!playedTitlesList)
playedTitlesList = [];

// Determine which titles are un-redeemed


var unredeemedTitleIds = [];
for (var i = 0; i < playedTitlesList.length; i++) {
if (!redeemedTitleRewards.hasOwnProperty(playedTitlesList[i]) && playedTitlesList[i] !==
script.titleId)
unredeemedTitleIds.push(playedTitlesList[i]);
}
if (unredeemedTitleIds.length === 0)
return null; // Nothing to redeem

// Give the cross title rewards


var multiplier = unredeemedTitleIds.length;
var actualRewards = {}; // MY_CROSS_TITLE_REWARDS is a global constant, so don't modify it or you'll
mess up future calls
// Please note that the number of API calls that may be made from CloudScript, as well as the total
available processing time is limited,
// and so the number of rewards should be as small as possible (only one VC, in this case)
for (var eachKey in MY_CROSS_TITLE_REWARDS) {
actualRewards[eachKey] = MY_CROSS_TITLE_REWARDS[eachKey] * multiplier;
server.AddUserVirtualCurrency({ PlayFabId: currentPlayerId, VirtualCurrency: eachKey, Amount:
MY_CROSS_TITLE_REWARDS[eachKey] }); // Can only add 1 VC at a time
}

// Save the Publisher data indicating rewards are claimed


redeemedTitleRewards[script.titleId] = playedTitlesList;
var setRequest = { PlayFabId: currentPlayerId, Data: { PUBLISHER_REDEEMED_TITLES_KEY:
JSON.stringify(redeemedTitleRewards) } };
server.UpdateUserPublisherInternalData(setRequest);

// Tell the client the reward


return actualRewards;
};

NOTE
This particular example demonstrates the use of server.GetUserPublisherInternalData (requesting multiple keys),
server.UpdateUserPublisherInternalData, and server.AddUserVirtualCurrency.

The code blocks represent these steps:


Fetching the data from PlayFab, and parsing it into local data structures (calling
GetUserPublisherInternalData).
Examining the data and search for un-rewarded title IDs.
Granting the rewards (calling AddUserVirtualCurrency).
Updating the claimed rewards (calling UpdateUserPublisherInternalData).
Making the rewarded amount available to the client (via return statement from CloudScript).

Conclusion
Player publisher data and player data are structurally identical.
Player data should be title-specific, while player publisher data should only contain information relevant across
all of your titles.

See also
Simple In-Game Cross Promotion: Reward players participating in more than one of your games.
Player Data Tutorials
5/24/2022 • 2 minutes to read • Edit Online

These tutorials describe how to create and use player statistics, profile information, and other types of player
data.
Getting player profiles
Player Ban system
Player inventory
Player Logins report
Player Segment configuration
Player Segments
PlayFab GDPR
Using Player details
Using Player Publisher Data
Using player statistics
Using the Players page
Tutorial: Get a player profile
5/24/2022 • 4 minutes to read • Edit Online

In this tutorial you learn how to:


Create a user with a display name
Make a player profile call
Get Player Created time and Last Login time
Configure the player profile view constraints for the title
Get the player profile via login operation

Requirements
A PlayFab developer account.
An installed copy of the Unity Editor. To install Unity for personal use via Unity Hub, or Unity+ for
professional use, see Download Unity.

NOTE
The PlayFab Unity3D SDK supports Unity Editor version 5.3 (released December 2015) and higher.

A Unity Project * this can be any of the following:


A brand new project. For more information, see Starting Unity for the first time.
A guided tutorial project. For more information, see Getting Started with Unity.
An existing project.
The PlayFab Unity3D SDK.
For this tutorial, basic knowledge of how to create a player for your title is needed, so that you can perform a
GetPlayerProfile on the player.

It is also worthwhile to read the Game Manager quickstart if you are unfamiliar with the Game Manager, as it is
the place where we configure profile constraints.
The C# Samples in this topic are written for the Unity SDK. The Unity SDK uses an event driven model to handle
non-synchronous tasks. To run the sample code using the standard C# or Xamarin C# SDKs you must modify
the code to use an async Task model. Methods that must be modified have Async append to the method name in
the signature. For example, SetObject in the Unity SDK becomes SetObjectAsync in the standard C# SDK. For
more information, see Asynchronous programming with async and await.

Create a user with a display name


The first step is to create a player and add a display name to the user. This example will create a new user with
the display name UnicornTossMaster .
void CreatePlayerAndUpdateDisplayName() {
PlayFabClientAPI.LoginWithCustomID( new LoginWithCustomIDRequest {
CustomId = "PlayFabGetPlayerProfileCustomId",
CreateAccount = true
}, result => {
Debug.Log("Successfully logged in a player with PlayFabId: " + result.PlayFabId);
UpdateDisplayName();
}, error => Debug.LogError(error.GenerateErrorReport()));
}

void UpdateDisplayName() {
PlayFabClientAPI.UpdateUserTitleDisplayName( new UpdateUserTitleDisplayNameRequest {
DisplayName = "UnicornTossMaster"
}, result => {
Debug.Log("The player's display name is now: " + result.DisplayName);
}, error => Debug.LogError(error.GenerateErrorReport()));
}

The console output should show:

Successfully logged in a player with PlayFabId: SOME_PLAYFAB_ID


The player's display name is now: UnicornTossMaster

Make a player profile call


The next step is to make a very basic profile for the player usin
The following example uses a basic GetPlayerProfile call.

void GetPlayerProfile(string playFabId) {


PlayFabClientAPI.GetPlayerProfile( new GetPlayerProfileRequest() {
PlayFabId = playFabId,
ProfileConstraints = new PlayerProfileViewConstraints() {
ShowDisplayName = true
}
},
result => Debug.Log("The player's DisplayName profile data is: " + result.PlayerProfile.DisplayName),
error => Debug.LogError(error.GenerateErrorReport()));
}

The response includes a PlayerProfileModel object that contains the display name UnicornTossMaster for the
player.

Get Player Created time and Last Login time


In the PlayerProfileModel object there is a fair amount of data about the player. In the previous step, a
GetPlayerProfile was issued, and the response that was received only contained display name information.

The next step is to get even more profile data for the player. To do so, call GetPlayerProfile with additional
fields in the PlayerProfileViewConstraints request parameter.
The following C# example modifies the GetPlayerProfile method from step 2 and calls GetPlayerProfile to
request the Created and LastLogin fields by setting their flags in the ProfileConstraints.

NOTE
This will be an unsuccessful call at this step!!!
void CreatePlayerAndUpdateDisplayName(string playFabId) {
PlayFabClientAPI.GetPlayerProfile( new GetPlayerProfileRequest() {
PlayFabId = playFabId,
ProfileConstraints = new PlayerProfileViewConstraints {
ShowDisplayName = true,
ShowCreated = true,
ShowLastLogin = true
}
},
result => Debug.Log("The player's profile Created date is: " + result.PlayerProfile.Created),
error => Debug.LogError(error.GenerateErrorReport()));
}

If you run this sample code at this point, it returns an error with an Error Code 1303 .
RequestViewConstraintParamsNotAllowed , and an error message stating that there are Invalid view constraints
with a JSON output of constraints that the title currently has set.
The error occurs because you have not yet configured the ability to show Created and LastLogin in your title's
profile constraint settings.

Configure the player profile view constraints for the title


To get more data when you call the GetPlayerProfile API, you need to configure the constraints on the data to be
available. These settings are in the title's settings in Game Manager.
By default, the ALLOW CLIENT ACCESS TO PROFILE PROPERTIES: had only Display name enable which
allowed you to retrieve Display Name value.
To configure additional constraints for the title:
In Game Manager, select your title.
Select the gear icon in the upper left-hand corner, then select Title settings .
Select the Client Profile Options tab.
To enable both Created and LastLogin in the ProfileConstraints, check Creation date and Last login
time , then select SAVE CLIENT PROFILE OPTIONS .
Now when you call 1 CreatePlayerAndUpdateDisplayName it returns the PlayerProfileModel object with data on the
user's creation time, last login, and the display name of UnicornTossMaster .

Get the player profile via login operation


In most cases you want to retrieve player profile data as soon as a player logs in. The PlayFab API allows you to
combine the log in call and the call to retrieve the player profile into a single call.
The following example shows how to gain profile information through a login request, and uses
LoginWithCustomId as an example.

NOTE
This works with every login mechanism.
void CreatePlayerAndUpdateDisplayName(string customId) {
PlayFabClientAPI.LoginWithCustomID( new LoginWithCustomIDRequest() {
CustomId = customId,
// Define info request parameters
InfoRequestParameters = new GetPlayerCombinedInfoRequestParams() {
// And make sure PlayerProfile is included
GetPlayerProfile = true,
// Define rules for PlayerProfile request
ProfileConstraints = new PlayerProfileViewConstraints() {
// And make sure that both AvatarUrl and LastLogin are included.
ShowAvatarUrl = true,
ShowLastLogin = true,
}
}
},
result =>
{
// Extract the data you have requested
var avatarUrl = result.InfoResultPayload.PlayerProfile.AvatarUrl;
},
error => Debug.LogError(error.GenerateErrorReport()));
}
Player inventory
5/24/2022 • 7 minutes to read • Edit Online

Requirements
In order to use the player inventory, you must have a catalog defined for your title. Please read our Catalogs
tutorial for more information.

NOTE
Optionally, you can also define stores for your catalog.

While a catalog is the list of all of the items available in the game, a store is a subset of items from the catalog
that has the option of unique pricing.
Multiple stores can be defined per catalog, so that you can have distinct sets of items for presentation to the
player, based upon user segmentation or other factors.
Once you have defined a catalog through the Game Manager , or though our admin SetCatalogItems or
UpdateCatalogItems API calls, you will be able to use a wide variety of Inventory API calls on the client and
server.

API Overview
All inventory API calls are designed to be server-authoritative and secure. Used properly, customers will not be
able to cheat or acquire items they did not earn.
Clients :
Buy Items with virtual currency: PurchaseItem
Make Real Money purchases: Star tPurchase , PayForPurchase , ConfirmPurchase
Can view the items a player has: GetUserInventor y
Can remove items: ConsumeItem , UnlockContainerInstance
Can trade items: OpenTrade , GetPlayerTrades , AcceptTrade , CancelTrade
Ser ver :
May Gift/Grant items: GrantItemsToUser
Can view the items: GetUserInventor y
Can modify items: ModifyItemUses , UpdateUserInventor yItemCustomData
Can remove items: RevokeInventor yItem , ConsumeItem , UnlockContainerInstance
The example shown below illustrates the code blocks that call these API methods, and sets up basic use-cases
for player inventory.

NOTE
For reference, these examples come from Unicorn Battle , a game we built as an example to demonstrate the PlayFab
features.

The AU virtual currency used below is Gold , a free currency earned by fighting monsters (See our Currencies
tutorial).
Before we get started, we will be defining a few utility functions that will be used and reused in most of the
examples in this guide.

// **** Shared example utility functions ****

// This is typically NOT how you handle success


// You will want to receive a specific result-type for your API, and utilize the result parameters
void LogSuccess(PlayFabResultCommon result) {
var requestName = result.Request.GetType().Name;
Debug.Log(requestName + " successful");
}

// Error handling can be very advanced, such as retry mechanisms, logging, or other options
// The simplest possible choice is just to log it
void LogFailure(PlayFabError error) {
Debug.LogError(error.GenerateErrorReport());
}

Client-only example: purchase and consume a health potion


Client API call order: PurchaseItem, GetUserInventory, ConsumeItem
First we must begin by defining the item in our catalog.
Here are the CatalogItem requirements for the Health Potion .
PurchaseItem requires a positive item price ( 5 AU ).
ConsumeItem requires the item to be Consumable , with a positive item count ( 3 ).
The player making the purchase must have 5 AU available in their virtual currency balance.
The code for each call is provided below.

void MakePurchase() {
PlayFabClientAPI.PurchaseItem(new PurchaseItemRequest {
// In your game, this should just be a constant matching your primary catalog
CatalogVersion = "CharacterClasses",
ItemId = "MediumHealthPotion",
Price = 5,
VirtualCurrency = "AU"
}, LogSuccess, LogFailure);
}

void GetInventory() {
PlayFabClientAPI.GetUserInventory(new GetUserInventoryRequest(), LogSuccess, LogFailure);
}

void ConsumePotion() {
PlayFabClientAPI.ConsumeItem(new ConsumeItemRequest {
ConsumeCount = 1,
// This is a hex-string value from the GetUserInventory result
ItemInstanceId = "potionInstanceId"
}, LogSuccess, LogFailure);
}

Example: player is granted and opens a container


API call order:
PlayFab Server API GrantItemsToUser
PlayFab Client API UnlockContainerInstance
First, we must begin with a container defined in our catalog. For our container in this example, we selected a
Cr ystalContainer .
This example also demonstrates opening the container with a key - an optional item which must also be in the
player inventory for the UnlockContainerInstance call to be successful.
CatalogItem requirements for our Cr ystalContainer in this example include:
That the Cr ystalContainer be defined as a Container .
That Containers can optionally define a Key Item , which is then required to unlock the Container - in
this case, a Cr ystalKey .
It is highly suggested that your Container and any Key both be Consumable , with a positive use count,
so that they are removed from the player inventory after use.
Server code
void GrantItem() {
PlayFabServerAPI.GrantItemsToUser(new GrantItemsToUserRequest {
// In your game, this should just be a constant
CatalogVersion = "CharacterClasses",
// Servers must define which character they're modifying in every API call
PlayFabId = "playFabId",
ItemIds = new List<string> { "CrystalContainer" }
}, LogSuccess, LogFailure);
}

Client code

void OpenContainer() {
PlayFabClientAPI.UnlockContainerInstance(new UnlockContainerInstanceRequest {
// In your game, this should just be a constant matching your primary catalog
CatalogVersion = "CharacterClasses",
ContainerItemInstanceId = "containerInstanceId",
KeyItemInstanceId = "keyInstanceId"
}, LogSuccess, LogFailure);
}

Consuming keys and containers


In the previous example, it is suggested that the key and/or container are consumable, though that's only a
recommendation.
But if a container and its key (if any) are not consumable, the container can be re-opened infinitely, granting its
contents to the player each time.
Because the player inventory capacity is not infinite, this pattern is greatly discouraged. When a consumable
container is unlocked, both it and the consumable key that was used will automatically have their usage count
decreased, removing them from the player inventory when the usage count reaches zero.
Viable options
Consumable Container , no Key : The most basic pattern, in which the container is consumed when opened,
and there is no key.
Consumable Container, consumable Key : The simple locked container case, which allows the player to open
the container with they key. Both are consumed, and the player can only open a container with uses remaining
with a key with uses remaining.
Durable Container, consumable Key : This allows a player to open the container every time they find a key.
The key is consumed, and the container is only opened while the key has uses remaining.
Consumable Container, durable Key : This allows a player to keep a key that can open all of the containers
for which it is the key item. The container is consumed, but the player retains the ability to open containers with
the key later.

Example: buying inventory items from the player


There is no built-in API for buying back inventory items from the player, as the process is game-specific.
However, you can use the existing API methods to craft your own SellItem experience:
The PlayFab Server API RevokeInventoryItem** allows you to remove an inventory item.
The PlayFab Server API AddUserVirtualCurrency** can return an appropriate amount of virtual currency.
It is not currently possible to return real money through PlayFab API methods.
NOTE
Items and virtual currencies have a close relationship. For more information, see our Currencies tutorial.

The following CloudScript function combines the two described server calls into a single client-accessible call.

var SELL_PRICE_RATIO = 0.75;


function SellItem_internal(soldItemInstanceId, requestedVcType) {
var inventory = server.GetUserInventory({ PlayFabId: currentPlayerId });
var itemInstance = null;
for (var i = 0; i < inventory.Inventory.length; i++) {
if (inventory.Inventory[i].ItemInstanceId === soldItemInstanceId)
itemInstance = inventory.Inventory[i];
}
if (!itemInstance)
throw "Item instance not found"; // Protection against client providing incorrect data
var catalog = server.GetCatalogItems({ CatalogVersion: itemInstance.CatalogVersion });
var catalogItem = null;
for (var c = 0; c < catalog.Catalog.length; c++) {
if (itemInstance.ItemId === catalog.Catalog[c].ItemId)
catalogItem = catalog.Catalog[c];
}
if (!catalogItem)
throw "Catalog Item not found"; // Title catalog consistency check (You should never remove a
catalog/catalogItem if any player owns that item
var buyPrice = 0;
if (catalogItem.VirtualCurrencyPrices.hasOwnProperty(requestedVcType))
buyPrice = catalogItem.VirtualCurrencyPrices[requestedVcType];
if (buyPrice <= 0)
throw "Cannot redeem this item for: " + requestedVcType; // The client requested a virtual currency
which doesn't apply to this item
// Once we get here all safety checks are passed - Perform the sell
var sellPrice = Math.floor(buyPrice * SELL_PRICE_RATIO);
server.AddUserVirtualCurrency({ PlayFabId: currentPlayerId, Amount: sellPrice, VirtualCurrency:
requestedVcType });
server.RevokeInventoryItem({ PlayFabId: currentPlayerId, ItemInstanceId: soldItemInstanceId });
}

handlers.SellItem = function (args) {


if (!args || !args.soldItemInstanceId || !args.requestedVcType)
throw "Invalid input parameters, expected soldItemInstanceId and requestedVcType";
SellItem_internal(args.soldItemInstanceId, args.requestedVcType);
};

Best practices
Make sure to verify all client input information as valid before making any changes.
CloudScript is not atomic, so call order matters: AddUserVir tualCurrency may succeed and
RevokeInventor yItem may fail.

TIP
It is generally better to give the player something they didn't earn in this process, than to take something away without
compensation.

This CloudScript function can then be accessed from the client.


void SellItem()
{
PlayFabClientAPI.ExecuteCloudScript(new ExecuteCloudScriptRequest
{
// This must match "SellItem" from the "handlers.SellItem = ..." line in the CloudScript file
FunctionName = "SellItem",
FunctionParameter = new Dictionary<string, string>{
// This is a hex-string value from the GetUserInventory result
{ "soldItemInstanceId", "sellItemInstanceId" },
// Which redeemable virtual currency should be used in your game
{ "requestedVcType", "AU" },
}
}, LogSuccess, LogFailure);
}
Using the Players page
5/24/2022 • 2 minutes to read • Edit Online

Monitoring players
It is possible to inspect the players you have in your title using the Players page.
Go to the Game Manager page.
Select Players from the menu on the left.
Select the Players tab.

On this page, You can inspect the list of registered players in a table format. The table contains general
information about the player.
You can select a player ID label (blue) to inspect details about a particular player. You can also use the Search
Quer y field to look up players.

Search Techniques
The Search query field accepts two types of queries:
1. Simple : Type plain text in the search box to return literal string matches on the ID column.
2. Complex : Construct queries using the KQL syntax.
Sample complex queries can be accessed from the Search Tips button in the upper right. Selecting a sample
query will automatically populate the search box with the correct KQL syntax. You can then edit the query to suit
your use case.
There are many attributes of the Player Profile table, not all of which are visualized in the UI. However, you may
search on any of these PlayerProfile columns using a complex query.
NOTE
Remember - you can use any searchable player field as a query parameter.
Using player details
5/24/2022 • 3 minutes to read • Edit Online

Accessing player details


1. To access player details, first select Players .
2. From the list, locate the player whose details you want to review, and select their ID . This displays the
Player Overview page.

Overview
The Player Over view (or details page), is a starting point for controlling your player. A lot of other player
pages are available from this page (we'll list them later in this tutorial).
1. The Player ID - Shows you the identity of the player you have selected.
2. The Player toolbar - Gives you access to various player-related pages.
3. The Run CloudScript button - Gives you access to cloud scripting on behalf of the player.

NOTE
You can read more about this in our CloudScript quickstart.

4. Information panels contain general information about the player account.


5. The PlayFab Account Panel offers pages for managing a player's PlayFab account (described later in
this tutorial).
6. The Accounts panel allows linking to different accounts for a single player record (described later in this
tutorial).
NOTE
You can read more about this in our CloudScript quickstart.

Player Toolbar Overview


PlayFab offers a wide set of pages for fine tuning and analyzing your player. These pages are available from the
Player toolbar panel, and consist of the following items:
Logins for inspecting a player's login attempts.
Segments for inspecting the segments that a player belongs to.
Statistics for inspecting and manipulating a player's statistical values.
Player Data (Title) for managing account data within the current scope.
Player Data (Publisher) for managing account data across several titles.
Virtual currency
Inventory for managing the items that a player owns.
Purchases
Friends for managing a player's friends list.
Characters
Multiplayers
Bans

Managing a player account


A PlayFab account contains critical, identifying, player data. As an administrator, you can change some of this
data.
1. PlayFab ID - The player ID identifies the player you are currently inspecting.
2. Display name - Allows you to edit the display name for this player.
3. Username - A read-only field for inspecting the player's username. Username can be empty. When present,
it can be used for a player to log in using a username and password.
4. Email - This field is hidden and locked due to PII concerns. The email field can be empty. When present, it can
be used for player to log in using email and password. You may use the Lock icon button to unlock and
change the email value.
5. Change Password - When set, this can be used to assign a new password for the user. This setting is
mutually exclusive with Send password reset email.
6. Send password reset email - When set, this allows you to send a password recover y email when an
email value is present. This setting is mutually exclusive with Change password .
7. Avatar image URL - This field allows you to force change avatar for the user.
8. Update PlayFab account - Use this button to commit any changes you make on this account screen.

Additionally, you can manage linking. Read more about linking in our quickstart on Account linking.
NOTE
It is only possible to manually link Custom ID, Android Device, or iOS Device accounts. For more sophisticated options
(Steam, GameCenter, etc.), consider using other Client Account Management APIs listed in our PlayFab API Reference
documentation.

Running CloudScript
The Run CloudScript button on the Player Over view page opens the REVISION AND FUNCTION page
shown below. On the REVISION AND FUNCTION screen:
1. The Run CloudScript button - Allows you to access a player's CloudScript settings.
2. Revision - Lets you select the revision level of the CloudScript to use. You can select Refresh to grab the
latest changes.
3. The Function name - Lets you select the function to run. The list of available functions is based on your
CloudScript revision content.
4. The Arguments field - Lets you supply optional JSON arguments.
5. The RUN CLOUDSCRIPT button - Lets you commit any changes you make on this screen.
Players logins
5/24/2022 • 2 minutes to read • Edit Online

The Players logins page offers an overview of all the login attempts for a specific player.

Access players logins


To access the players logins page:
1. Select Players found in the sidebar menu.
2. Select the Players tab.
3. From the list, select the ID of the player you want to inspect.
4. Then, select Logins in the Players toolbar.

Overview
The Players Login page contains the following information:
Player ID - A label that identifies the player you are inspecting.
Total login attempts - The total number of login attempts by this player.
Date of login attempt - A human readable date label for each login attempt.
IP address - A label showing the IP address.
Source - A label that indicates where the login attempt came from.
Result - Indicates whether the login attempt was successful.
Player ban system
5/24/2022 • 2 minutes to read • Edit Online

The player ban feature allows you to restrict access to the game for certain players who break the rules.

NOTE
Bans can be temporary or permanent.

The following tutorial shows you how to utilize the ban system, using the PlayFab API and Game Manager.

Identify
While your game may have a custom system to identify cheaters and rule-breakers, PlayFab offers a player-to-
player reporting mechanism. In essence, you rely on your players to report other problematic players.
Use the following snippet in your client code to let the client report a specific player.

public void ReportPlayer(string problematicPlayerId, string reason) {


PlayFabClientAPI.ReportPlayer(new ReportPlayerClientRequest() {
ReporteeId = problematicPlayerId,
Comment = reason
}, result => {
//... Handle success
}, error => {
Debug.Log(error.GenerateErrorReport());
});
}

This API call will produce:


A Repor t Event , which you will be able to locate via the Analytics tool (1) .
Select the player_repor ted_as_abusive event type (2) .
This will show:
The Event Name (3) .
The reported Player ID (4) .
Applying bans
Once the problematic player is identified, you may apply a ban. A community management rep may also apply a
ban using Game Manager.
1. Navigate to the Players section.
2. Locate and select the problematic Player.
3. Navigate to the Bans tab.
4. Select Add Ban to display the Add Ban form.
5. Type in the Reason for the ban, and the desired duration. Optionally, you can Ban by a specific IP ADDRESS
(4) .
6. Last, select the ADD BAN button.

If everything is set correctly, you will see a new Ban in the table. You may optionally remove a Ban manually by
selecting it in the REVOKE BANS field.

Creating a ban on the server


Alternatively, you may use the Server SDK to apply a ban via code by using the snippet provided below.
public void AddBan(string playerId, uint hours) {
PlayFabServerAPI.BanUsers(new BanUsersRequest() {
Bans = new List<BanRequest>() {
new BanRequest() {
DurationInHours = hours,
PlayFabId = playerId,
Reason = "Automatic ban for WH",
}
}
}, result => {
//... Handle success
}, error => {
Debug.Log(error.GenerateErrorReport());
});
}

Bans applied via code will also be displayed in the table of bans for the target player in Game Manager.

NOTE
The PlayFab server SDK methods provide more options, such as IP and MAC address bans.

Each ban you apply gets an assigned ID. Consider the following Server SDK API methods for precise ban
management:
GetUserBans
RevokeAllBansForUser
RevokeBans
UpdateBans

NOTE
You can use CloudScript functions as part of an automated system that may ban a player. To find out more about
CloudScript, see our tutorial Writing Custom CloudScript.
Player segments
5/24/2022 • 2 minutes to read • Edit Online

Players can be collected together into a segment, with the idea that all players in the segment meet certain
conditions (filters).
Once the segment is defined, you can monitor the total number of players in the segment and run custom
actions on those players automatically or manually.

Access players segments


To access player segments:
Navigate to Players (1) in the menu.
Select the Segments tab (2) .

Overview
The Segments page displays the segments that you currently have defined, and offers basic management
capabilities.
1. Use the NEW SEGMENT (1) button to create a new segment.
2. The segment ID (2) uniquely identifies the segment.
3. The segment Name (3) identifies the player(s).
4. The Matching players (4) area displays the total number of players matching the segment filter.
5. Using the check boxes (5) to the left of the screen, you can select certain segments, and X Delete or > Run
Task ... custom actions on the chosen segments.
For more information about defining segments and the filtering criteria, see our tutorial on Player
Segment configuration.
For more information about executing custom code for all players in a segment (as a one-time event, or
on a regular schedule), see our tutorial on Bulk Actions for an Entire Player Segment.
Player segment configuration
5/24/2022 • 6 minutes to read • Edit Online

The segment configuration page allows you to configure new or existing segments. You can:
Adjust the name.
Define the filters.
Assign tasks.
Each segment allows you to define useful or interesting groups of players, and perform exclusive actions on that
group.

How to create or access a segment


To access segment configuration:
1. On the left side select the Players area.
2. Select the Segments tab. From there you can then opt to:
Use the New Segment button to create and configure a new Segment*.
Locate an existing Segment, and select its Name label to configure the Segment.

How to configure a segment


Prerequisites
Some things must already exist for you to configure a segment. There must already be:
Players with and without a distinctive characteristic defined in PlayFab.
A defined CloudScript PlayStream hook.

NOTE
For more about this, see Using CloudScript actions with PlayStream.
Configuring
In this example we are going to:
Configure a segment using the defining characteristic that: all players that come from Canada.
Run a CloudScript function helloWorld for each player that enters the segment.
A defining characteristic of a player might be a:
Login time
Linked device type
Tags
A real-world location
Their statistic values
Their virtual currency values
Real money purchases, etc.

NOTE
Player's location is only one of your many possible options, and is only required for this example. Feel free to replace the
country/region requirement with another filter of your choice.

When a segment is defined, you have a variety of action options to run when a player enters or leaves the
segment.
CloudScript is by far the most flexible action, granting you full control of the player and segment information at
the time of segment-transition.
Use the second parameter - context - in your CloudScript handler to identify the player and segment transition.
Afterwards, you can perform any action you wish for the player, such as granting inventory items, virtual
currency, player data, or statistics.
In our example shown here, the segment configuration requires 4 simple steps.
1. Assign an appropriate Segment name (1) (in our example, that's Canadian Players ).
2. In the Player (2) area, assign any conditions that the Player must meet to enter the segment. (In our
example, we want a Location (countr y/region) filter with a strict value: Canada .
3. In the Type area, add an Execute CloudScript (3) action for the entered segment trigger.
4. Configure the action to run the function we want (helloWorld (3) ).
5. Use the Save Segment button (4) to commit your activities.
Advanced segment filtering
Segment filtering allows you to define what players are included in the segment.
Formally speaking, area (1) on the left of the screen shown below is a set of Players that belong to at least one
group.
Group (2) is a set of Players that meet all defined conditions, called filters (3) .
So to be part of a segment:
A player must be part of at least 1 group.
To be part of a group, a player must meet all conditions (filters).
This is denoted by the OR/AND operators:
Filters are combined using the AND operator.
Groups are combined using the OR operator.
The screenshot shown above is an example of how a segment can be defined. This segment consists of 2
groups:
1. The first group is defined by 2 filters:
A player must be from Canada. a. And must have Apple push notifications enabled.
The second group is also for players from Canada, but they must have Google push notifications
enabled.
In the end, we have a segment of players from Canada with either Google or Apple push notifications.
Each filter has a unique configuration and purpose. As of 4/30/2017 the following filters are available:
All Players filter - This filter has no configuration and is unique, because it allows you to create a
segment of all players. This comes in handy when you want to run automatic operations for every new
player (segment actions are described later in this tutorial).
First login (date) filter - Allows you to filter based on the first login datetime (example - players that
have first logged in after 1/1/2017).
First login (timespan) filter - Allows you to filter based on first login timespan relative to the current
datetime (example - players that have first signed in 20 minutes ago [from now]).
Last login (date) filter - Allows you to filter based on the last login datetime (example - players that
have not signed in since 1/1/2017).
Last login (timespan) filter - Allows you to filter based on the last login timespan relative to the current
datetime (example, players that have not signed in for a week [from now]).
Linked user account to filter - Allows you to filter based on the users' linked accounts (example -
players that have a Steam account linked with email).
Location (countr y/region) filter - Allows you to filter based on player's country/region (example -
players from Canada).
Push notifications enabled with filter - Allows you to filter based on player push notification settings
and capabilities (example - players that have Google push notifications enabled.
Statistics value filter - Allows you to filter based on your own custom statistic attribute (example -
players that inflicted 20000 damage in total).
Tag filter - Allows you to filter based on whether a player has or doesn't have a certain tag (example -
players that have a cheater tag).
Total value to date in USD filter - Allows you to filter based on how much USD currency a player spent
in your game (example - players that have spent over $30.
Value to date filter - Allows you to filter based on how much of a certain currency a player spent in your
game (example - players that have spent 50 RUB).
User Origination filter - Allows you to filter based on the first authentication method that a player used
to start playing the game.

NOTE
The trick here is that a player may start with authentication based on, say, an iOS Device ID. Later, a player may have a
GameCenter account linked. In this case, the player origination will be the iOS Device ID (example, players that first signed
in using an iOS Device ID).

Vir tual currency balance filter - Allows you to filter based on a player's custom virtual currency deposit
(example - players that have less than 50 Crystal).

How to manage actions


Each action needs a trigger in order to run. Some actions are run manually, triggered right from the page.
But sometimes, you have to select a trigger - an event that causes an action to run. A trigger defines the context
of the action.
For example, the Player Entered Segment Trigger passes you the context containing a reference to the player.
The general workflow for the Actions panel is the following:
1. Select an event condition (1) a.k.a a trigger.
2. Select the Type of action.

NOTE
PlayFab offers a variety of actions. If, at any point, you need a more flexible action, consider a CloudScript action. This
action type allows you to run your own CloudScript function.

3. Configure the action (3) (specific for each action type).


4. Remove an action (4) from the trigger.
5. Use Add Action (5) to add an action to the trigger.
How to inspect player segments
It is possible to look up what segments a player belongs to by means of the Player Segments page.
To access Player Segments:
1. Select the Players section.
2. Select the Players tab.
3. Click on the ID label for the player you want to inspect.
4. Select Segments in the Players toolbar.

On the Player Segments page, you will see the following:


The Player ID (1) label identifies the player that you are currently inspecting.
The Segment table contains a list of all the segments that a player belongs to.
Select the Segment name label (2) to configure the segment.
PlayFab GDPR - Deleting and exporting player data
5/24/2022 • 8 minutes to read • Edit Online

PlayFab is committed to being General Data Protection Regulation (GDPR) compliant - and as your service
provider, ensuring that we provide you with the hooks you need to allow Players to view or delete the data
stored about them.
While we can’t provide you with legal advice — and we do encourage you to seek legal counsel to ensure your
compliance with the GDPR — we are here to help you fulfill your obligations under GDPR.
PlayFab has three available APIs to help you respond to Player data requests:
GetPlayedTitleList - Call this API to get a list of TitleIds which have data associated with the given player. This
list is scoped by PublisherID and represents the set of titles which would be impacted were you to delete or
export this player's data.
DeleteMasterPlayerAccount - Call this API to delete the records of a given player.
ExportMasterPlayerData - Call this API to export all of the associated data and records of a given player.

Make sure you find all the data


Before using the DeleteMasterPlayerAccount or ExportMasterPlayerData APIs, it is important to keep in mind that
your players might have created multiple Master Player accounts with your studio.
This can happen when a player uses different devices or different credentials to play your title(s). Because they
are providing different and unrelated credentials (e.g. a different email address or social media account), we
interpret them to be a unique player.
Another way a player may have multiple Master Player accounts is if you have configured your studio to use
multiple Publisher IDs; however, having multiple Publisher IDs is not common.
You can check your title's Publisher IDs in the PlayFab Game Manager, on each Title settings menu's API
Features tab.

You know your titles and how they authenticate your players. Before calling DeleteMasterPlayerAccount or
ExportMasterPlayerData , make sure you collect the right set of device IDs and/or credentials from your players.

With these credentials, we can identify the PlayFabIds for each Master Player account.
The following APIs will help you translate from credential to PlayFabId :
GetUserAccountInfo - This API will help you find players by email, TitleDisplayName , PlayFabId , or a
PlayFabUsername .
GetPlayerIdFromAuthToken - This API will allow you to find a player from a specific AuthToken which is
granted to the player when they log in.
GetPlayFabIDsFromFacebookIDs - This API derives the player's PlayFabId from one or more FacebookId (s).
GetPlayFabIDsFromSteamIDs - This API derives the player's PlayFabId from one or more SteamIds .

NOTE
All of these APIs are title-specific. The first two are Admin APIs and the last two are Server APIs.

Even if your player only has one PlayFabId, they may have played more than one of your titles with that ID. This
means their data request may span multiple titles.
To get this list of titles, call GetPlayedTitleList for each PlayFabId. You may wish to inform the player their
request will impact the returned list of titles.
Additionally, GetPlayedTitleList returns TitleIds , not Title Names - consider converting these to
Title Names before displaying them in a confirmation page.
Here's a little pseudo code to paint a better picture of what we mean...

//Here you would iterate through a request of known Ids, Emails, linked accounts
//or other PlayFab searchable info on the player that you have.
//and store it in user credentials for that player.
user {
credentials: (email/ids/linked accounts)
}

//create a variable to hold a list of all the PlayFabIds you want to remove.
PlayFabIdList

//create a list of affected titles


AffectedTitles

//Keep track of all your titles, this is important


//and should include all titles across all your namespaces.
foreach(title in <all my titles>){

//each user record you have for the player, you should have a list of credentials for that player
//so you can find them in PlayFab
foreach(cred in user.credentials){
//There are a few helper Admin and Server API's that help you do this part.
//See below this pseudo code block for some tips!
pfid = <find PlayFabId in Title using the credential>
PlayFabIdList.add(pfid)
}

//go through the list of PlayFabIds that you have and fine all titles that
//performing the action would affect
foreach(pfid in PlayFabIdList){
AffectedTitles = title.GetPlayedTitleList(pfid)
}
}

Here is a quick example on how to use GetPlayedTitleList .


public static async void StartFindTitlesExample(Action<PlayFabError> callback)
{

var task = await PlayFabAdminAPI.GetPlayedTitleListAsync(new GetPlayedTitleListRequest() {


PlayFabId = PlayFabId
});

if(task.Error != null)
{
callback(task.Error);
return;
}

var TitleList = task.Result.TitleIds;


foreach (var title in TitleList)
{
Console.WriteLine(string.Format("Title Found: {0}", title));
}
callback(null);
}

At this this point you have a list of PlayFabIds for this player (based on the credentials they’ve shared) and a list
of titles for each PlayFabId . Now what?
Now you’re ready to delete or export!

Deleting a Master Player account


Deleting a Master Player account can be accomplished by using the new DeleteMasterPlayerAccount Admin API
which is available in all of our SDKs. Please make sure you read the section above, which details how to make
sure you have all of a player's PlayFabIds.
When you make a request to delete a player, PlayFab will quickly remove the player's personal information from
our core system before sending the request to a queue processing agent, which works to remove any remaining
information about the player from ancillary systems and sub-processors.
This API returns immediately and provides a JobReceiptId , which you should store for your records. The
JobReceiptId is your validation that PlayFab received the request to delete the player.
Once the delete is complete, an email will be sent to the notification email address configured for the title. It will
contain the same JobReceiptId , which was initially returned by the API. The completion of the task will also
trigger a PlayStream event.
Using our Webhook feature, you can register to receive these events on an endpoint of your choosing, and
process them as needed. The event will contain a JSON blob that has the JobReceiptId .
The following example shows how to use the Admin API with the C# SDK. If you would like to use a different
SDK, select one from the list of PlayFab SDKs.
public static async void StartDeleteMasterPlayerExample(Action<PlayFabError> callback)
{
var task = await PlayFabAdminAPI.DeleteMasterPlayerAccountAsync(new DeleteMasterPlayerAccountRequest()
{
PlayFabId = PlayFabId
});

if(task.Error != null)
{
callback(task.Error);
}

var jobReceiptId = task.Result.JobReceiptId;


var AffectedTitleList = task.Result.TitleIds;
foreach (var title in AffectedTitleList)
{
Console.WriteLine(string.Format("Delete Player - Title Affected: {0}", title));
}

NOTE
Because this deletion cannot be undone, we suggest confirming with your player that they are comfortable with the
scope and impact of their deletion request.

So, once the action has been confirmed… Back to pseudo code.

//Make sure we are 100% sure we want to do this.


if ( confirm successful ) {
//create a variable to store a list of titles the player has already been removed from.
listOfTitlesRemovedFrom
//Hang on to the receipts from successful deletes.
listOfReceipts
foreach(title in <all my titles>){

//You only need to remove the Master Player once per namespace, so check that you have not
//already performed this action in the namespace, or you will get an error that
//the player is already queued for deletion.
if(title not in listOfTitlesRemovedFrom){
foreach(pfid in PlayFabIdList){

//Note: you should do some error handling around this API call.
response = title.DeleteMasterPlayerAccount(pfid)
foreach(titleId in response.titleids){
listOfTitlesRemoved.add(titleId)
}
listOfReceipts.add(response.jobreceiptid)
}
}
}

//Save listOfReceipts somewhere as proof of deletion.

Exporting Master Player account data


When you make a request to export a player's data, the request is sent to a Queue Processing Agent (similar
to deleting a player).
The ExportMasterPlayerData API exports all data associated with the given PlayFabId , including data across all
your titles, such as:
Statistics
Custom Data
Inventor y
Purchases
Vir tual Currency Balances
Characters
Group Memberships
Publisher Data
Credential Data
Account Linkages
Friends List
PlayStream Event Histor y .
Please make sure you read the first section above which details how to make sure you have all of a player’s
PlayFabIds.
This API immediately returns a JobReceiptId , which you should store in your records for future reference. It
may take some time before the export is available for download.
Upon completion of the export, an email containing the URL to download the export dump will be sent to the
notification email address configured for the title.
The completion of the task will also trigger a PlayStream event. Using our Webhook feature, you can register to
receive these events on an endpoint of your choosing and process as needed. The event will contain a JSON
blob that has information such as the JobReceiptId and the download URL for the exported data.
The following example is how to use the Admin API with the C# SDK. If you would like to use a different SDK,
select one from the list of PlayFab SDKs.

public static async void ExportMasterPlayerExample(Action<PlayFabError> callback)


{
var task = await PlayFabAdminAPI.ExportMasterPlayerDataAsync(new ExportMasterPlayerDataRequest()
{
PlayFabId = PlayFabId
});

if(task.Error != null)
{
callback(task.Error);
}

var jobReceiptId = task.Result.JobReceiptId;

Console.WriteLine(string.Format("Export Player Request Received - Receipt: {0}", jobReceiptId));

callback(null);
}
NOTE
The URL will be available for up to 30 days after the export has completed. After this time, the file will be deleted, and you
will need to initiate a new export request.

Other considerations
It is easy to do harm with these APIs. Exporting data for or deleting the wrong player could be very damaging
and it is permanent!
It is your responsibility as the game developer to verify that the credentials are owned by the player requesting
an export or deletion of their player data. PlayFab does not provide any type of verification when using these
APIs.
However PlayFab does offer an email verification feature. But our solution is not the only option for verification.
You can create your own process too.
Regardless of which technology you use, we suggest that you do some sort of verification before performing
any of these actions.

Are we done yet?


You should receive an email when your request has completed. If, for some reason, it never arrives (because that
happens sometimes in our digital world), contact us at privacy@playfab.com with a request for verification.
Please provide the JobReceiptId in that email, and we will respond letting you know the status of that job.
Using player statistics
5/24/2022 • 3 minutes to read • Edit Online

This tutorial describes how to create and use player statistics. Player statistics are stored as Key Value Pairs
(KVPs) where the Key is a string, and the Value is a 32-bit integer (for compatibility with languages which do not
support 64-bit).
Player statistics are also used by leaderboards, but this guide only covers player statistics exclusively. If you wish
to read about how player statistics and leaderboards work together, please read our tutorial Using resettable
statistics and leaderboards.

NOTE
In some documentation and API calls, you may find the term UserStatistics . For the purposes of this discussion, the
terms user and player are identical and interchangeable. In the Game Manager page, the Players tab provides access
to the Users/Players for your title, and within that, their statistics. Player statistics refers specifically to information
bound to a player, not analytics information about player.

Client API
The client has access to read player statistics, but to prevent cheating, the client is not able to update statistics by
default.
To enable this:
Log into PlayFab
Select your Title .
Select Settings from the left-menu.
Select the API Features tab.
Find and activate Allow client to post player statistics .

NOTE
Doing this disables a security layer for your title, allowing players to post arbitrary scores to all of their statistics. If your
game has any competitive play aspect, we would recommend that you never post statistics from the client.

Statistics are public information


There are no private or server-only statistics. A player can always read all of their own statistics via
GetPlayerStatistics, and can read all other players' statistics via leaderboard API calls. This is true even if you
don't display a statistic in-game, or use leaderboards.
The only exception to this would be if you disable client features through our API Access Policy. Please refer to
that link for more information on how to use the policy settings for titles, as that is an advanced topic which is
not covered by this tutorial.

Setting statistics
The following Unity/C# code creates (or updates if it already exists) a strength statistic value for a player.
PlayFabClientAPI.UpdatePlayerStatistics( new UpdatePlayerStatisticsRequest {
// request.Statistics is a list, so multiple StatisticUpdate objects can be defined if required.
Statistics = new List<StatisticUpdate> {
new StatisticUpdate { StatisticName = "strength", Value = 18 },
}
},
result => { Debug.Log("User statistics updated"); },
error => { Debug.LogError(error.GenerateErrorReport()); });

Getting statistics
The following Unity/C# code retrieves all current statistic values for a player.

void GetStatistics()
{
PlayFabClientAPI.GetPlayerStatistics(
new GetPlayerStatisticsRequest(),
OnGetStatistics,
error => Debug.LogError(error.GenerateErrorReport())
);
}

void OnGetStatistics(GetPlayerStatisticsResult result)


{
Debug.Log("Received the following Statistics:");
foreach (var eachStat in result.Statistics)
Debug.Log("Statistic (" + eachStat.StatisticName + "): " + eachStat.Value);
}

Aggregation method
PlayFab supports some convenience options for Statistic Aggregation. The 4 options include:
Last
Min
Max
Sum
You can create a statistic definition via the CreatePlayerStatisticDefinition API call, though it's not required. Any
call to update a player statistic for the title will automatically create the default statistic definition, using the Last
Aggregation method.
To change a statistic aggregation method, you can use the Game Manager or the UpdatePlayerStatisticDefinition
API call.
To edit a statistic definition in Game Manager :
Log into PlayFab
Select your Title .
Select Leaderboards from the menu on the left (Statistics and Leaderboards are closely related).
Select the existing statistic you want to modify, or -
Select the New Leaderboard button.
For an existing statistic, you'll have another page, with an Edit Leaderboard button.
At this point you should see the page shown below.
Some examples of how to use statistic aggregation:
Max and Min can be used to save best/worst scores such as Headshots or Accuracy:
In short, they apply the rule of: if this is higher (or lower) than the existing score, update the
score .
Post the statistic for the session ending, and the Min/Max Aggregation takes care of whether or not
to update.
These can be very useful for resettable leaderboards, as well as a PlayStream Rule that grants
achievements.
Sum could be used to save experience points:
You post the experience gained this battle, and it is added to the existing statistic value for the player.
Last allows you to manage the stat yourself:
Each time you post a statistic, the most recent value is used.

Leaderboards
A leaderboard is generated for all statistics saved in PlayFab. Accessing a leaderboard for a specific stat is
optional.
Reset frequency and aggregation methods play a major role in how dynamic the leaderboards are in your game.
The Tournaments feature focuses on leaderboards with automatic reset frequencies, and is described in the
tutorial Using resettable statistics and leaderboards.
We encourage you to use statistics in every manner relevant to your game. You can use resettable statistics to
run daily tournaments, and long-term statistics like experience points, side-by-side.
Title Data
5/24/2022 • 2 minutes to read • Edit Online

Title Data is a set of key/value pairs that you can use to manage configuration for your game remotely. You can
set this data in Game Manager, or via APIs. This is commonly referred to as Primary Title Data.
Internal Title Data is a special set of Title Data that cannot be accessed by clients directly, and can be used for
storing configuration that is only available to services you control.

NOTE
Title Data values are copied and distributed to potentially hundreds of machines in the PlayFab server cluster. As part of
this process, Title Data is cached, and changes may take up to fifteen minutes to refresh in those caches. Title Data is best
suited for Global Constant/Static Data and is not suitable or reliable as Global Variables.

Title Data Overrides


Title Data Overrides are sets of key/value pairs which are stored and managed to override the Primary Title
Data. This override set of key/value pairs persist as an additive operation. Using Override, one can:
Add a new key-value pair, by naming a key-value pair that isn’t included in the default data.
Change an existing key-value pair by naming a key-value pair that’s already in the default data. This new
data will replace the existing key-value data.
Remove an existing key-value pair by including an existing key but with an empty value.
When viewing the Override, each of these key-value pairs is represented as a +, , or -.
Override Title Data could be called a subset of Primary Title Data, allowing to update the remote configuration
of the game without the need to deploy a new build.
NOTE
This override set of key/value pairs comes in-effect only using Experiments for now. If the player belongs to an experiment
variant which contain title data overrides, the overrides are applied automatically on server side and returned with the
title data on client side. Title Data Override values may take up to one minute to refresh and persist.

Links
Title Data quickstart
Title Data Tutorials
Title Data quickstart
5/24/2022 • 3 minutes to read • Edit Online

Title data is the set of plain text key-value pairs, used for storing and managing the game’s configuration data
remotely on the server. It keeps the title wide configuration variables accessible and organized which can be
retrieved on the client-side.
This QuickStart describes how to programmatically create and use title data.
This an important topic because storing a game's configuration data remotely on the server - where it can be
changed at any time - is one of the most basic reasons to use a service like PlayFab.

Getting title data


From the game client
Use GetTitleData from the PlayFabClientAPI to get the KVPs for a specific title. The following code example
displays the values of all of the title data.

public void ClientGetTitleData() {


PlayFabClientAPI.GetTitleData(new GetTitleDataRequest(),
result => {
if(result.Data == null || !result.Data.ContainsKey("MonsterName")) Debug.Log("No MonsterName");
else Debug.Log("MonsterName: "+result.Data["MonsterName"]);
},
error => {
Debug.Log("Got error getting titleData:");
Debug.Log(error.GenerateErrorReport());
}
);
}

From the game server


Use GetTitleData from the PlayFabServerAPI to get the KVPs for a specific Title. The following code example
displays the values of all of the Title Data.

public void ServerGetTitleData() {


PlayFabServerAPI.GetTitleData( new GetTitleDataRequest(),
result => {
if (result.Data == null || !result.Data.ContainsKey("MonsterName")) Debug.Log("No MonsterName");
else Debug.Log("MonsterName: " + result.Data["MonsterName"]);
},
error => {
Debug.Log("Got error getting titleData:");
Debug.Log(error.GenerateErrorReport());
});
}

Setting title data


It is unlikely that title data will change very frequently. For most situations, you should use your title data for
static data that is mostly unchanged for the life of the title.
You can set title data by using the Game Manager, or by a server API function.
Setting title data using Game Manager
To add Primary Title Data using Game Manager to a title, perform the following steps.
1. Open the title in Game Manager .
2. Select Content , then Title Data .
3. Select New Title Data
4. In the new title data page, enter a value for the Key and a value for the Value . Both the Key and the Value
are stored as strings.
5. Use the Save button to save the new data item.

Setting title data by calling the server API in C#


The SetTitleData API is a server API that you must call from a dedicated server. You can only set one title data
KVP in each call to SetTitleData .

public void SetTitleData() {


PlayFabServerAPI.SetTitleData(
new SetTitleDataRequest {
Key = "MonsterName",
Value = "Dorf"
},
result => Debug.Log("Set titleData successful"),
error => {
Debug.Log("Got error setting titleData:");
Debug.Log(error.GenerateErrorReport());
}
);
}

Setting title data overrides using Game Manager


An override is also a set of JSON key-value pairs and ideally should be purposed to possess the delta change
required in the key-values pairs of the Primary Title Data. The delta change could comprise of the key-value
pairs when compared to Primary Title data as new key-value, change in an existing key’s value or deletion of a
key (with NULL as an input of the value).
To add overrides to the primary title data, perform the following steps.
1. Open the title in Game Manager .
2. Select Content , then Title Data .
3. Select New Override .
4. Enter the Override Label, plus, enter a value for the Key and a value for the Value . Both the Key and the
Value are stored as strings.
5. Use the Save button to save the new Title Data Override.

NOTE
This override set of key/value pairs comes in-effect only using Experiments for now. If the player belongs to an experiment
variant which contain title data overrides, the overrides are applied automatically on server side and returned with the
title data on client side. Title Data Override values may take up to one minute to refresh and persist.
Internal title data
Similarly to User Data, title data has internal storage that is hidden from the client. This data can also be set in
the Game Manager, or via a server API.
Getting internal title data by calling the server API in C#

public void GetTitleInternalData()


{
PlayFabServerAPI.GetTitleInternalData( new GetTitleDataRequest(),
result => {
if (result.Data == null || !result.Data.ContainsKey("PlayFab")) Debug.Log("No PlayFab");
else Debug.Log("PlayFab: " + result.Data["PlayFab"]);
},
error => {
Debug.Log("Got error getting titleData:");
Debug.Log(error.GenerateErrorReport());
}
);
}

Setting internal title data by calling the server API in C#

public void SetTitleInternalData() {


PlayFabServerAPI.SetTitleInternalData(
new SetTitleDataRequest {
Key = "PlayFab",
Value = "{ \"Status\": \"Secretly Awesome\" }"
},
result => { Debug.Log("Set titleData successful"); },
error =>
{
Debug.Log("Got error setting titleData:");
Debug.Log(error.GenerateErrorReport());
});
}

See also
Using Publisher Data
Player Data Quickstart
CloudScript Quickstart
Title Data Tutorials
5/24/2022 • 2 minutes to read • Edit Online

These tutorials describe how to programmatically create and use publisher and title data.
Using publisher data
Using Publisher data
5/24/2022 • 4 minutes to read • Edit Online

This tutorial describes how to create and use Publisher (Studio) data.
Publisher data is data that spans more than one title - such as when you have multiple games that need to share
common information.

NOTE
This category also includes data for players that spans multiple games. PlayFab stores data as Key/Value Pairs (KVPs).

Most of these APIs are server APIs that your program must call from a dedicated server, or through a
CloudScript function within the PlayFab service.
Use the server APIs SetPublisherData to update, and GetPublisherData to retrieve, Publisher-specific
custom KVPs.
Use UpdateUserPublisherData to create or update, and GetUserPublisherData to retrieve, Publisher-
specific custom KVPs for the player.
Use the server API UpdateUserPublisherReadOnlyData to update, and the client API
GetUserPublisherReadOnlyData to retrieve, the read-only Publisher-specific custom KVPs for the user.
Use the server APIs UpdateUserPublisherInternalData to update, and GetUserPublisherInternalData
to retrieve, the internal Publisher-specific custom KVPs for the user.
You must call the server APIs from a dedicated server or through a CloudScript function through the PlayFab
service. This is by design, as the PlayFab server APIs require that you supply your secret key.

TIP
We do not recommend using server APIs from within a game client. If you need to make use of a server API, use
CloudScript for this type of functionality.

Publisher data values are copied and distributed to potentially hundreds of machines in the PlayFab cluster
server. As part of this process, this data is cached and changes may take up to fifteen minutes to refresh in those
caches.

NOTE
Publisher data is best suited for global constant/static data, and is not suitable or reliable as global variables.

Publisher data
Publisher data is used to store static data for a set of titles. Each entry is not bound to any PlayFab entity, such as
a player (as opposed to user publisher data).
Setting Publisher data
The following snippet demonstrates how to set Publisher data using the Server API.
NOTE
There is an admin API counterpart for this operation.

public void ServerSetPublisherData() {


PlayFabServerAPI.SetPublisherData(new SetPublisherDataRequest() {
Key = "SomeKey",
Value = "SomeValue"
},
result => Debug.Log("Complete setting publisher data"),
error => {
Debug.Log("Got error setting publisher data");
Debug.Log(error.GenerateErrorReport());
}
);
}

Getting Publisher data


The following snippet demonstrates getting Publisher data using the Client API.

NOTE
There are server and admin API counterparts for this operation.

public void ClientGetPublisherData() {


PlayFabClientAPI.GetPublisherData(new GetPublisherDataRequest(),
result => {
if (result.Data == null || !result.Data.ContainsKey("SomeKey")) Debug.Log("No SomeKey");
else Debug.Log("SomeKey: " + result.Data["SomeKey"]);
},
error => {
Debug.Log("Got error getting publisher data");
Debug.Log(error.GenerateErrorReport());
});
}

User Publisher data


User Publisher data can be used to introduce Publisher data that is bound to a PlayFab user (player).
Unlike regular Publisher data, it is possible for a Client application to alter user Publisher data.
PlayFab exposes 3 protection levels for user Publisher data from the Client API point of view:
1. Regular user Publisher data exposes read and write access for client applications.
Set via Client, Server, and Admin API.
Get via Client, Server, and Admin API.
The Client API may only set Publisher data for a player who is currently logged in.
2. Read-only user Publisher data exposes read access for client applications.
Set via Server and Admin API.
Get via Client, Server, and Admin API.
3. Internal user Publisher data exposes no access for client applications, and is used to store the secret
portion of user data.
Set via Server and Admin API.
Get via Server and Admin API.
Setting user Publisher data
The following snippet demonstrates how to set all 3 kinds of Publisher data using Client and Server APIs.

// Use Client API to set User Publisher Data for current user
public void ClientSetUserPublisherData() {
PlayFabClientAPI.UpdateUserPublisherData(new UpdateUserDataRequest() {
Data = new Dictionary<string, string>() {
{ "SomeKey", "SomeValue" }
}
},
result => Debug.Log("Complete setting Regular User Publisher Data"),
error =>
{
Debug.Log("Error setting Regular User Publisher Data");
Debug.Log(error.GenerateErrorReport());
});
}

// Use Server API to set Read-Only User Publisher Data for selected user
public void ServerSetUserPublisherReadOnlyData() {
PlayFabServerAPI.UpdateUserPublisherReadOnlyData(new UpdateUserDataRequest() {
PlayFabId = "< PlayFab Player Id >",
Data = new Dictionary<string, string>() {
{ "SomeKey", "SomeValue" }
}
},
result => Debug.Log("Complete setting Read-Only User Publisher Data"),
error =>
{
Debug.Log("Error setting Read-Only User Publisher Data");
Debug.Log(error.GenerateErrorReport());
});
}

// Use Server API to set Internal User Publisher Data for selected user
public void ServerSetUserPublisherInternalData() {
PlayFabServerAPI.UpdateUserPublisherInternalData(new UpdateUserInternalDataRequest() {
PlayFabId = "< PlayFab Player Id >",
Data = new Dictionary<string, string>() {
{ "SomeKey", "SomeValue" }
}
},
result => Debug.Log("Complete setting Internal User Publisher Data"),
error =>
{
Debug.Log("Error setting Internal User Publisher Data");
Debug.Log(error.GenerateErrorReport());
});
}

Getting user Publisher data


The following snippet demonstrates how to get all 3 kinds of Publisher data using Client and Server APIs.
// Use Client API to get Regular User Publisher Data for selected user
public void ClientGetUserPublisherData() {
PlayFabClientAPI.GetUserPublisherData(new GetUserDataRequest() {
PlayFabId = "<PlayFab Player Id>"
}, result => {
if (result.Data == null || !result.Data.ContainsKey("SomeKey")) Debug.Log("No SomeKey");
else Debug.Log("SomeKey: " + result.Data["SomeKey"]);
},
error => {
Debug.Log("Got error getting Regular Publisher Data:");
Debug.Log(error.GenerateErrorReport());
});
}

// Use Client API to get Read-Only User Publisher Data for selected user
public void ClientGetUserPublisherReadOnlyData() {
PlayFabClientAPI.GetUserPublisherReadOnlyData(new GetUserDataRequest() {
PlayFabId = "<PlayFab Player Id>"
}, result => {
if (result.Data == null || !result.Data.ContainsKey("SomeKey")) Debug.Log("No SomeKey");
else Debug.Log("SomeKey: " + result.Data["SomeKey"]);
},
error => {
Debug.Log("Got error getting Read-Only Publisher Data:");
Debug.Log(error.GenerateErrorReport());
});
}

// Use Server API to get Internal User Publisher Data for selected user
public void ServerGetUserPublisherInternalData() {
PlayFabServerAPI.GetUserPublisherInternalData(new GetUserDataRequest() {
PlayFabId = "<PlayFab Player Id>"
}, result => {
if (result.Data == null || !result.Data.ContainsKey("SomeKey")) Debug.Log("No SomeKey");
else Debug.Log("SomeKey: " + result.Data["SomeKey"]);
},
error => {
Debug.Log("Got error getting Internal Publisher Data:");
Debug.Log(error.GenerateErrorReport());
});
}

See also
Title Data quickstart
CloudScript quickstart
Entity Programming Model
5/24/2022 • 5 minutes to read • Edit Online

Entities are the most basic addressable "things" that PlayFab APIs operate on. Each entity has a Type and an Id
which together uniquely identify it. Some types of entities are "standard" or "built-in", in that PlayFab knows
something about their meaning and/or automatically creates them, for example namespace , title , group ,
master_player_account , and title_player_account . Others might have no inherent meaning to PlayFab but have
meaning in your game.
Every entity has a profile that contains various resources owned by that entity. For example, objects, files,
language settings, policies, and others to come. An entity profile is retrieved directly with the GetProfile API,
and many other APIs operate on specific resources inside of the profile, such as SetObjects .
Finally, there are parent/child relationships between entities which factor into the permissions governing how an
entity's resources may be accessed by other entities. The "ancestors" of a given entity can be found in the
Lineage property of its profile.

Comparison with Classic API


With that out of the way, let's look at the differences between the "classic" and "entity" APIs. If you are using the
classic APIs, you are already working with the same entities that you can use with the entity APIs, but they're not
always explicit. For example, in the Client API, UpdateUserData operates on a title_player_account entity,
GetUserPublisherData operates on a master_player_account , GetCharacterStatistics operates on a character
(that is a child of the title_player_account ), GetTitleData operates on a title and GetPublisherData operates
on a namespace .
In general, each classic API operates on one specific type of entity, but the entity type is often implicit and doesn't
necessary follow from the API name. Moreover, the equivalent APIs for two types of entities may subtly vary
with respect to their parameters, limits, and behavior (e.g. UpdatePlayerStatistics vs.
UpdateCharacterStatistics ). If you're feeling confused by this, you aren't alone. We wanted to simplify the
PlayFab APIs without ever breaking compatibility with the existing set, which takes us to...
"Entity APIs" are what we've been calling the newer PlayFab APIs which adhere to the following design goals
(with some exceptions).
Work with arbitrary types of entities.
Have explicit parameters for the entity Type and Id.
Perform a specific operation on a specific resource in the entity profile.
Can be called in multiple security contexts, such as from game clients, game servers, Cloud Script, back-end
servers, etc., with the permissions defined by policies and selected according to which entity is calling the API.
We believe that following these principles will result in fewer APIs that do more, are more efficient to maintain
and operate, and are easier for developers to learn. Basically, this is the way we would design all PlayFab APIs if
we were to start over, knowing everything we've learned over the past five years about how developers are
using PlayFab. Of course, one of our most important principles at PlayFab is to never break live titles, if at all
possible, which means we must maintain backward compatibility with all released APIs.

Considerations for Classic API users


To accomplish our design goals while maintaining compatibility, we have been introducing these entity APIs as a
separate set for the most part, existing side-by-side with the classic APIs. While the entity APIs can work with the
same entities as the classic APIs, in most cases they operate on a separate set of resources / data owned by
these entities. For example, the SetObjects entity API and the UpdateUserData classic API can both store data
under a title_player_account entity, but the data that the two APIs "see" is completely separate. Here are some
of the practical implications:
The bad
If your title is already using classic APIs for data, inventories, etc. with players (a.k.a. title_player_account s),
that existing data will not automatically show up in the equivalent entity APIs.
It will take some time before the entity APIs have feature parity with the classic APIs. The data is stored
separately in most cases, and there are a lot of back-end changes required to support them. There may be
some classic functionality that never makes it to the entity API.
The good
You don't have to do anything. If your game is already working well on PlayFab classic APIs, it will continue to
work.
You can start using entity APIs while continuing to use classic APIs on the same set of entities. In some
situations there are clear benefits to doing this, at little cost, e.g. adding a new feature to your game that
saves larger amounts of data in a file, in addition to existing settings stored in classic "player data".

Functionality Overview
The entity programming model is the foundation for PlayFab's next generation of data and game services.
Authentication
Profiles
Groups
Data - File
Data - Object
Events
CloudScript
Multiplayer
Supported Entity types
The following list describes the available Entity types, which can be used to construct an EntityKey . Entity Keys
are used to identify entities in most newer API methods.
These values are meant to be used in the EntityKey.Type field.

NOTE
These are case sensitive. Other/custom values will not currently work.

Namespace
Namespace is the singular Entity that refers to all global information for every Title within a Studio. This
information should be static. Changes to this Entity are not reflected in real time.
Set the ID field to your GamePublisherId . To retrieve your GamePublisherId :
Log in to Game Manager.
From the My Studios and Titles page, select the appropriate Title.
Select the gear icon in the left corner of the Title page and then select Title Settings .
Select the API Features tab.
The Publisher ID on the API Features page is your GamePublisherId .
Title
Title is the singular Entity that refers to all global information for that Title. This information should be static.
Changes to this Entity are not reflected in real time.
Set the ID field to your game's TitleId . To retrieve your TitleId :
Log in to Game Manager.
On the My Studios and Titles page locate your Title.
The Title ID is located just below the name of your Title.
master_player_account
The master_player_account is a Player Entity that is shared among all Titles within a Studio.
Set the ID field to PlayFabId from the Classic API, returned by any LoginResult.PlayFabId .
title_player_account
title_player_account , for most developers, represents the Player in the most traditional way.
Set the ID field to LoginResult.EntityToken.Id in the Client API, or GetEntityTokenResponse.Entity.Id in the
Authentication API.
Character
Character is a sub-entity of title_player_account and is a direct mirror of Characters in the Classic APIs.
Set the ID field to any characterId from result.Characters[i].CharacterId .
Group
Group is an Entity that contains other Entities. It is currently limited to Players and Characters.
Set the ID field to the result.Group.Id if you are creating a group, or the result.Groups[i].Group.Id when
listing your memberships.
Entities quickstart
5/24/2022 • 9 minutes to read • Edit Online

This entities quickstart demonstrates how to work with entity objects and entity files.
For information on migrating from the legacy account and data systems to PlayFab entities, see Entities
migration information

Requirements
A PlayFab developer account.
An installed copy of the Unity Editor. For information on installing the Unity Editor, see Installing Unity in the
Unity documentation. You can also install a version of the Unity using the Visual Studio feature installer.

NOTE
The PlayFab Unity3D SDK supports Unity Editor version 5.3 and higher.

A Unity Project. For information on creating a Unity Project, see the Quickstart guide.

NOTE
If you are unfamiliar with Unity, recent installation packages give you the option of installing game creation
walkthroughs. You can use one of the walkthroughs to create a sample game to use in the following quickstart.

The PlayFab Unity3D SDK.


The C# Samples in this topic are written for the Unity SDK. The Unity SDK uses an event driven model to handle
non-synchronous tasks. To run the sample code using the standard C# or Xamarin C# SDKs you must modify
the code to use an async Task model. Methods that must be modified have Async append to the method name in
the signature. For example, SetObject in the Unity SDK becomes SetObjectAsync in the standard C# SDK. For
more information, see Asynchronous programming with async and await.

Terminology
Entities are any PlayFab concept that can contain data. The built-in entity types are:
title - A title contains global information available to all players. This is similar to TitleData. It is identified by
the title ID ( TitleId ) of the game/application.
master_player_account - This entity Type allows you to share information about a player across multiple
games within a namespace. It is identified by the player ID ( PlayFabId ) of the player, which is returned as
part of any login or any call to retrieve account information for the player account (for example, the PlayFab
Client API GetAccountInfo).
title_player_account - Identifies a player account that contains some information for the current title. This
is identified by the entity ID ( EntityKey.Id ) you get back in the EntityKey object on any login.
character - Identifies a character that the player owns which contains information that you can retrieve. It is
identified by the character ID ( CharacterId ) of the character.
For more information on the built-in entity types, see Available built-in Entity types.
Entity initialization
To call any of the Entity API you must obtain the entity ID and entity Type . You use the ID and Type to make
calls to other Entity API methods. These are members of an EntityKey object.
You do this by calling any of the login methods, such as LoginWithCustomID .

void Login()
{
var request = new PlayFab.ClientModels.LoginWithCustomIDRequest
{
CustomId = SystemInfo.deviceUniqueIdentifier,
CreateAccount = true,
};
PlayFabClientAPI.LoginWithCustomID(request, OnLogin, OnSharedFailure);
}

void OnLogin(PlayFab.ClientModels.LoginResult result)


{
entityId = result.EntityToken.Entity.Id;
// The expected entity type is title_player_account.
entityType = result.EntityToken.Entity.Type;
}

You can also obtain the entity ID and entity Type by calling the GetEntityToken method.

PlayFabAuthenticationAPI.GetEntityToken(new GetEntityTokenRequest(),
(entityResult) =>
{
var entityId = entityResult.Entity.Id;
var entityType = entityResult.Entity.Type;
}, OnPlayFabError); // Define your own OnPlayFabError function to report errors

When called from the client, this typically represents the logged-in player. When called from game servers, this
represents your title.

Entity objects
Entity objects allow you to read and write small JSON-serializable objects attached to an entity. All entity types
support the GetObjects and SetObjects methods.
The following code snippets show how to set and read an Object on a title_player_account entity.
Use the SetObjects method to set entity objects on a player or a title.
var data = new Dictionary<string, object>()
{
{"Health", 100},
{"Mana", 10000}
};
var dataList = new List<SetObject>()
{
new SetObject()
{
ObjectName = "PlayerData",
DataObject = data
},
// A free-tier customer may store up to 3 objects on each entity
};

PlayFabDataAPI.SetObjects(new SetObjectsRequest()
{
Entity = new EntityKey {Id = entityId, Type = entityType}, // Saved from GetEntityToken, or a specified
key created from a titlePlayerId, CharacterId, etc
Objects = dataList,
}, (setResult) => {
Debug.Log(setResult.ProfileVersion);
}, OnPlayFabError);

Use the GetObjects method to retrieve entity objects on a player or a title.

var getRequest = new GetObjectsRequest {Entity = new EntityKey {Id = entityId, Type = entityType}};
PlayFabDataAPI.GetObjects(getRequest,
result => { var objs = result.Objects; },
OnPlayFabError
);

Entity files
Entity files allow you to read and write files attached to an entity, in any format.
Use the GetFiles method to retrieve entity files.

void LoadAllFiles()
{
if (GlobalFileLock != 0)
throw new Exception("This example overly restricts file operations for safety. Careful
consideration must be made when doing multiple file operations in parallel to avoid conflict.");

GlobalFileLock += 1; // Start GetFiles


var request = new PlayFab.DataModels.GetFilesRequest { Entity = new PlayFab.DataModels.EntityKey {
Id = entityId, Type = entityType } };
PlayFabDataAPI.GetFiles(request, OnGetFileMeta, OnSharedFailure);
}

Use the initiatefileuploads method to initiate a file upload to an entity's profile.


void UploadFile(string fileName)
{
if (GlobalFileLock != 0)
throw new Exception("This example overly restricts file operations for safety. Careful
consideration must be made when doing multiple file operations in parallel to avoid conflict.");

ActiveUploadFileName = fileName;

GlobalFileLock += 1; // Start InitiateFileUploads


var request = new PlayFab.DataModels.InitiateFileUploadsRequest
{
Entity = new PlayFab.DataModels.EntityKey { Id = entityId, Type = entityType },
FileNames = new List<string> { ActiveUploadFileName },
};
PlayFabDataAPI.InitiateFileUploads(request, OnInitFileUpload, OnInitFailed);
}

Use the AbortFileUploads method to abort a pending file upload to an entity's profile.

void OnInitFailed(PlayFabError error)


{
if (error.Error == PlayFabErrorCode.EntityFileOperationPending)
{
// This is an error you should handle when calling InitiateFileUploads, but your resolution path
may vary
GlobalFileLock += 1; // Start AbortFileUploads
var request = new PlayFab.DataModels.AbortFileUploadsRequest
{
Entity = new PlayFab.DataModels.EntityKey { Id = entityId, Type = entityType },
FileNames = new List<string> { ActiveUploadFileName },
};
PlayFabDataAPI.AbortFileUploads(request, (result) => { GlobalFileLock -= 1;
UploadFile(ActiveUploadFileName); }, OnSharedFailure); GlobalFileLock -= 1; // Finish AbortFileUploads
GlobalFileLock -= 1; // Failed InitiateFileUploads
}
else
OnSharedFailure(error);
}

Use the FinalizeFileUploads method to finalize file uploads to an entity's profile. The entity system does not
consider the file upload complete, nor reflect any changes to other callers until the atomic upload operation is
successfully finalized.

void FinalizeUpload(byte[] data)


{
GlobalFileLock += 1; // Start FinalizeFileUploads
var request = new PlayFab.DataModels.FinalizeFileUploadsRequest
{
Entity = new PlayFab.DataModels.EntityKey { Id = entityId, Type = entityType },
FileNames = new List<string> { ActiveUploadFileName },
};
PlayFabDataAPI.FinalizeFileUploads(request, OnUploadSuccess, OnSharedFailure);
GlobalFileLock -= 1; // Finish SimplePutCall
}

The example shown below demonstrates a full entity-file loop, from logging in, to loading a file, and uploading a
new file.
The steps for this are:
login and retrieve the entity ID and entity Type .
Initialize the atomic upload operation.
Upload all of the files.
Finalize the atomic upload operation.
For simplicity, this example saves one file at a time, but files can be uploaded atomically in sets.
The example assumes that you're familiar with using the Unity 3D engine.

#if !DISABLE_PLAYFABENTITY_API && !DISABLE_PLAYFABCLIENT_API

using PlayFab;
using PlayFab.Internal;
using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine;

public class EntityFileExample : MonoBehaviour


{
public string entityId; // Id representing the logged in player
public string entityType; // entityType representing the logged in player
private readonly Dictionary<string, string> _entityFileJson = new Dictionary<string, string>();
private readonly Dictionary<string, string> _tempUpdates = new Dictionary<string, string>();
public string ActiveUploadFileName;
public string NewFileName;
// GlobalFileLock provides is a simplistic way to avoid file collisions, specifically designed for this
example.
public int GlobalFileLock = 0;

void OnSharedFailure(PlayFabError error)


{
Debug.LogError(error.GenerateErrorReport());
GlobalFileLock -= 1;
}

// OnGUI provides a way to build a Unity GUI entirely within script.


- // Your GUI will be game-specific.
void OnGUI()
{
if (!PlayFabClientAPI.IsClientLoggedIn() && GUI.Button(new Rect(0, 0, 100, 30), "Login"))
Login();
if (PlayFabClientAPI.IsClientLoggedIn() && GUI.Button(new Rect(0, 0, 100, 30), "LogOut"))
PlayFabClientAPI.ForgetAllCredentials();

if (PlayFabClientAPI.IsClientLoggedIn() && GUI.Button(new Rect(100, 0, 100, 30), "(re)Load Files"))


LoadAllFiles();

if (PlayFabClientAPI.IsClientLoggedIn())
{
// Display existing files
_tempUpdates.Clear();
var index = 0;
foreach (var each in _entityFileJson)
{
GUI.Label(new Rect(100 * index, 60, 100, 30), each.Key);
var tempInput = _entityFileJson[each.Key];
var tempOutput = GUI.TextField(new Rect(100 * index, 90, 100, 30), tempInput);
if (tempInput != tempOutput)
_tempUpdates[each.Key] = tempOutput;
if (GUI.Button(new Rect(100 * index, 120, 100, 30), "Save " + each.Key))
UploadFile(each.Key);
index++;
}
// Apply any changes
foreach (var each in _tempUpdates)
_entityFileJson[each.Key] = each.Value;
// Add a new file
NewFileName = GUI.TextField(new Rect(100 * index, 60, 100, 30), NewFileName);
if (GUI.Button(new Rect(100 * index, 90, 100, 60), "Create " + NewFileName))
UploadFile(NewFileName);
}
}

void Login()
{
var request = new PlayFab.ClientModels.LoginWithCustomIDRequest
{
CustomId = SystemInfo.deviceUniqueIdentifier,
CreateAccount = true,
};
PlayFabClientAPI.LoginWithCustomID(request, OnLogin, OnSharedFailure);
}

void OnLogin(PlayFab.ClientModels.LoginResult result)


{
entityId = result.EntityToken.Entity.Id;
entityType = result.EntityToken.Entity.Type;
}

void LoadAllFiles()
{
if (GlobalFileLock != 0)
throw new Exception("This example overly restricts file operations for safety. Careful
consideration must be made when doing multiple file operations in parallel to avoid conflict.");

GlobalFileLock += 1; // Start GetFiles


var request = new PlayFab.DataModels.GetFilesRequest { Entity = new PlayFab.DataModels.EntityKey {
Id = entityId, Type = entityType } };
PlayFabDataAPI.GetFiles(request, OnGetFileMeta, OnSharedFailure);
}

void OnGetFileMeta(PlayFab.DataModels.GetFilesResponse result)


{
Debug.Log("Loading " + result.Metadata.Count + " files");

_entityFileJson.Clear();
foreach (var eachFilePair in result.Metadata)
{
_entityFileJson.Add(eachFilePair.Key, null);
GetActualFile(eachFilePair.Value);
}
GlobalFileLock -= 1; // Finish GetFiles
}

void GetActualFile(PlayFab.DataModels.GetFileMetadata fileData)


{
GlobalFileLock += 1; // Start Each SimpleGetCall
PlayFabHttp.SimpleGetCall(fileData.DownloadUrl,
result => { _entityFileJson[fileData.FileName] = Encoding.UTF8.GetString(result); GlobalFileLock
-= 1; }, // Finish Each SimpleGetCall
error => { Debug.Log(error); }
);
}

void UploadFile(string fileName)


{
if (GlobalFileLock != 0)
throw new Exception("This example overly restricts file operations for safety. Careful
consideration must be made when doing multiple file operations in parallel to avoid conflict.");

ActiveUploadFileName = fileName;

GlobalFileLock += 1; // Start InitiateFileUploads


var request = new PlayFab.DataModels.InitiateFileUploadsRequest
{
{
Entity = new PlayFab.DataModels.EntityKey { Id = entityId, Type = entityType },
FileNames = new List<string> { ActiveUploadFileName },
};
PlayFabDataAPI.InitiateFileUploads(request, OnInitFileUpload, OnInitFailed);
}

void OnInitFailed(PlayFabError error)


{
if (error.Error == PlayFabErrorCode.EntityFileOperationPending)
{
// This is an error you should handle when calling InitiateFileUploads, but your resolution path
may vary
GlobalFileLock += 1; // Start AbortFileUploads
var request = new PlayFab.DataModels.AbortFileUploadsRequest
{
Entity = new PlayFab.DataModels.EntityKey { Id = entityId, Type = entityType },
FileNames = new List<string> { ActiveUploadFileName },
};
PlayFabDataAPI.AbortFileUploads(request, (result) => { GlobalFileLock -= 1;
UploadFile(ActiveUploadFileName); }, OnSharedFailure); GlobalFileLock -= 1; // Finish AbortFileUploads
GlobalFileLock -= 1; // Failed InitiateFileUploads
}
else
OnSharedFailure(error);
}

void OnInitFileUpload(PlayFab.DataModels.InitiateFileUploadsResponse response)


{
string payloadStr;
if (!_entityFileJson.TryGetValue(ActiveUploadFileName, out payloadStr))
payloadStr = "{}";
var payload = Encoding.UTF8.GetBytes(payloadStr);

GlobalFileLock += 1; // Start SimplePutCall


PlayFabHttp.SimplePutCall(response.UploadDetails[0].UploadUrl,
payload,
FinalizeUpload,
error => { Debug.Log(error); }
);
GlobalFileLock -= 1; // Finish InitiateFileUploads
}

void FinalizeUpload(byte[] data)


{
GlobalFileLock += 1; // Start FinalizeFileUploads
var request = new PlayFab.DataModels.FinalizeFileUploadsRequest
{
Entity = new PlayFab.DataModels.EntityKey { Id = entityId, Type = entityType },
FileNames = new List<string> { ActiveUploadFileName },
};
PlayFabDataAPI.FinalizeFileUploads(request, OnUploadSuccess, OnSharedFailure);
GlobalFileLock -= 1; // Finish SimplePutCall
}
void OnUploadSuccess(PlayFab.DataModels.FinalizeFileUploadsResponse result)
{
Debug.Log("File upload success: " + ActiveUploadFileName);
GlobalFileLock -= 1; // Finish FinalizeFileUploads
}
}
#endif
NOTE
Each file action requires many steps and multiple API calls, so don't try to access the same file in multiple ways at the
same time. If you are very careful, you might not need a locking mechanism. If you want to do something complicated,
your locking mechanism may be much more complex.

Game Manager and entities


The Game Manager allows you to manipulate objects and files for players. The player overview shows both the
title player and master player account information.

In addition, files and objects now have their own sections in the Players tab.

See also
Introducing Entities, Objects and Files on the PlayFab blog.
Available built-in entity types
5/24/2022 • 2 minutes to read • Edit Online

This topic describes the available entity types that you can use to construct an EntityKey.
Entity keys identify entities in most of the newer API methods.
You use the value of the EntityKey.Type field to determine the type of value to set in the ID field.

NOTE
Entity keys are case sensitive.

namespace
The namespace entity refers to all global information for all titles within your studio.

NOTE
Changes to this entity are not reflected in real time.

Set the ID field to your game's Publisher ID . To retrieve your Publisher ID :


Sign in to Game Manager.
In the upper left-hand corner of Game Manger , select the gear icon.
Select Title Settings .
Select API Features .
The Publisher ID is displayed in the API ACCESS section.

title
The title entity refers to all global information for that title.

NOTE
Changes to this entity are not reflected in real time.

Set the ID field to your game's Title ID . To retrieve the Title ID :


Sign in to Game Manager.
In the upper left-hand corner of Game Manger , select the gear icon.
Select Title Settings .
Select API Features .
The Title ID is displayed in the API ACCESS section.

master_player_account
The master_player_account is a player entity that is shared by all titles within your studio.
Set the ID field to the LoginResult.PlayFabId from the classic API. To retrieve the LoginResult , call one of the
login methods in Client Authentication.

title_player_account
For most developers, title_player_account represents the player in the most traditional way.
Set the ID field to LoginResult.EntityToken.Entity.Id in the client API, or GetEntityTokenResponse.Entity.Id in
the authentication API.
To retrieve the , call one of the login methods in Client Authentication. To retrieve the
LoginResult
GetEntityTokenResponse , call Get Entity Token.

character
The character entity is a sub-entity of title_player_account , and is a direct mirror of Characters in the Classic
APIs.
Set the ID field to any characterId from result.Characters[i].CharacterId .

group
The group entity is a container for other entities. It is currently limited to players and characters.
Set the ID field to the result.Group.Id if you are creating a group, or the result.Groups[i].Group.Id when
listing your memberships.

service
The service entity is reserved for internal use.
Entities migration information
5/24/2022 • 2 minutes to read • Edit Online

The entity API introduces new access patterns that are designed to alleviate the pain points of the current
account and data systems.
The information presented here is useful if you have previously used the following methods to implement data
management for your Title, Player, or Character information.
Title access:
client/GetTitleData
admin/GetTitleData
server/GetTitleData
Player access:
client/GetUserReadOnlyData
client/UpdateUserData
client/UpdateUserPublisherData
Character access:
client/GetCharacterData
client/UpdateCharacterData
Using the entities API, you can call a single method to save the data values for title, player, and character entity
types. The API provides access rules that replicate and expand the current system behavior of custom data in a
better interface.
In some regards, these changes are not backwards compatible. However, you can add calls to the entity API
without changing the behavior of the existing APIs.

Terminology
The following table describes refinements in terminology related to the entity APIs.

T ERM DESC RIP T IO N

title This concept is unchanged. Your title may contain global


information available to all players. This is similar to
TitleData. It is identified by the title ID ( TitleId ) of the
game/application.

master_player_account This entity Type allows you to share information about a


player across multiple games within a studio. This is similar
to UserPublisherData. It is identified by the player ID (
PlayFabId ) of the player, which is returned as part of any
login or any call to retrieve account information for the
player account (for example, the PlayFab Client API
GetAccountInfo).
T ERM DESC RIP T IO N

title_player_account This concept is based on user/player in the existing API


methods. Each player can contain some information for the
current title. This is similar to the GetUserData method. This
is identified by the entity ID ( EntityKey.Id ) you get back
in the EntityKey object on any login where you specify
LoginTitlePlayerAccountEntity as True .

character This concept is unchanged. Your player may own characters,


which can each contain some information. This is similar to
CharacterData. It is identified by the character ID (
CharacterId ) of the character.

PlayFabId Formerly this term covered both master_player_account


and title_player_account concepts. Separating these
concepts simplifies and clarifies the functionality. A player can
interact with multiple titles that are all in the same studio, so
while they can have unique information as a different
title_player_account in each title, the owner of the
studio also needs to identify that player as a single
master_player_account entity with shared data across
titles. This enables things like cross-promotion of games and
giving players cross-game rewards.

See also
Introducing Entities, Objects and Files on the PlayFab blog.
Entities quickstart
Entity files
5/24/2022 • 4 minutes to read • Edit Online

Entity files allow you to read and write files attached to an entity, in any format. The example shown below
demonstrates a full entity-file loop, from logging in, to loading a file, and uploading a new file.

#if !DISABLE_PLAYFABENTITY_API && !DISABLE_PLAYFABCLIENT_API

using PlayFab;
using PlayFab.Internal;
using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine;

public class EntityFileExample : MonoBehaviour


{
public string entityId; // Id representing the logged in player
public string entityType; // entityType representing the logged in player
private readonly Dictionary<string, string> _entityFileJson = new Dictionary<string, string>();
private readonly Dictionary<string, string> _tempUpdates = new Dictionary<string, string>();
public string ActiveUploadFileName;
public string NewFileName;
public int GlobalFileLock = 0; // Kind of cheap and simple way to handle this kind of lock

void OnSharedFailure(PlayFabError error)


{
Debug.LogError(error.GenerateErrorReport());
GlobalFileLock -= 1;
}

void OnGUI()
{
if (!PlayFabClientAPI.IsClientLoggedIn() && GUI.Button(new Rect(0, 0, 100, 30), "Login"))
Login();
if (PlayFabClientAPI.IsClientLoggedIn() && GUI.Button(new Rect(0, 0, 100, 30), "LogOut"))
PlayFabClientAPI.ForgetAllCredentials();

if (PlayFabClientAPI.IsClientLoggedIn() && GUI.Button(new Rect(100, 0, 100, 30), "(re)Load Files"))


LoadAllFiles();

if (PlayFabClientAPI.IsClientLoggedIn())
{
// Display existing files
_tempUpdates.Clear();
var index = 0;
foreach (var each in _entityFileJson)
{
GUI.Label(new Rect(100 * index, 60, 100, 30), each.Key);
var tempInput = _entityFileJson[each.Key];
var tempOutput = GUI.TextField(new Rect(100 * index, 90, 100, 30), tempInput);
if (tempInput != tempOutput)
_tempUpdates[each.Key] = tempOutput;
if (GUI.Button(new Rect(100 * index, 120, 100, 30), "Save " + each.Key))
UploadFile(each.Key);
index++;
}
// Apply any changes
foreach (var each in _tempUpdates)
_entityFileJson[each.Key] = each.Value;

// Add a new file


// Add a new file
NewFileName = GUI.TextField(new Rect(100 * index, 60, 100, 30), NewFileName);
if (GUI.Button(new Rect(100 * index, 90, 100, 60), "Create " + NewFileName))
UploadFile(NewFileName);
}
}

void Login()
{
var request = new PlayFab.ClientModels.LoginWithCustomIDRequest
{
CustomId = SystemInfo.deviceUniqueIdentifier,
CreateAccount = true,
LoginTitlePlayerAccountEntity = true
};
PlayFabClientAPI.LoginWithCustomID(request, OnLogin, OnSharedFailure);
}
void OnLogin(PlayFab.ClientModels.LoginResult result)
{
entityId = result.EntityToken.Entity.Id;
entityType = result.EntityToken.Entity.Type;
}

void LoadAllFiles()
{
if (GlobalFileLock != 0)
throw new Exception("This example overly restricts file operations for safety. Careful
consideration must be made when doing multiple file operations in parallel to avoid conflict.");

GlobalFileLock += 1; // Start GetFiles


var request = new PlayFab.DataModels.GetFilesRequest { Entity = new PlayFab.DataModels.EntityKey {
Id = entityId, Type = entityType } };
PlayFabDataAPI.GetFiles(request, OnGetFileMeta, OnSharedFailure);
}
void OnGetFileMeta(PlayFab.DataModels.GetFilesResponse result)
{
Debug.Log("Loading " + result.Metadata.Count + " files");

_entityFileJson.Clear();
foreach (var eachFilePair in result.Metadata)
{
_entityFileJson.Add(eachFilePair.Key, null);
GetActualFile(eachFilePair.Value);
}
GlobalFileLock -= 1; // Finish GetFiles
}
void GetActualFile(PlayFab.DataModels.GetFileMetadata fileData)
{
GlobalFileLock += 1; // Start Each SimpleGetCall
PlayFabHttp.SimpleGetCall(fileData.DownloadUrl,
result => { _entityFileJson[fileData.FileName] = Encoding.UTF8.GetString(result); GlobalFileLock
-= 1; }, // Finish Each SimpleGetCall
error => { Debug.Log(error); }
);
}

void UploadFile(string fileName)


{
if (GlobalFileLock != 0)
throw new Exception("This example overly restricts file operations for safety. Careful
consideration must be made when doing multiple file operations in parallel to avoid conflict.");

ActiveUploadFileName = fileName;

GlobalFileLock += 1; // Start InitiateFileUploads


var request = new PlayFab.DataModels.InitiateFileUploadsRequest
{
Entity = new PlayFab.DataModels.EntityKey { Id = entityId, Type = entityType },
FileNames = new List<string> { ActiveUploadFileName },
};
};
PlayFabDataAPI.InitiateFileUploads(request, OnInitFileUpload, OnInitFailed);
}
void OnInitFailed(PlayFabError error)
{
if (error.Error == PlayFabErrorCode.EntityFileOperationPending)
{
// This is an error you should handle when calling InitiateFileUploads, but your resolution path
may vary
GlobalFileLock += 1; // Start AbortFileUploads
var request = new PlayFab.DataModels.AbortFileUploadsRequest
{
Entity = new PlayFab.DataModels.EntityKey { Id = entityId, Type = entityType },
FileNames = new List<string> { ActiveUploadFileName },
};
PlayFabDataAPI.AbortFileUploads(request, (result) => { GlobalFileLock -= 1;
UploadFile(ActiveUploadFileName); }, OnSharedFailure); GlobalFileLock -= 1; // Finish AbortFileUploads
GlobalFileLock -= 1; // Failed InitiateFileUploads
}
else
OnSharedFailure(error);
}
void OnInitFileUpload(PlayFab.DataModels.InitiateFileUploadsResponse response)
{
string payloadStr;
if (!_entityFileJson.TryGetValue(ActiveUploadFileName, out payloadStr))
payloadStr = "{}";
var payload = Encoding.UTF8.GetBytes(payloadStr);

GlobalFileLock += 1; // Start SimplePutCall


PlayFabHttp.SimplePutCall(response.UploadDetails[0].UploadUrl,
payload,
FinalizeUpload,
error => { Debug.Log(error); }
);
GlobalFileLock -= 1; // Finish InitiateFileUploads
}
void FinalizeUpload()
{
GlobalFileLock += 1; // Start FinalizeFileUploads
var request = new PlayFab.DataModels.FinalizeFileUploadsRequest
{
Entity = new PlayFab.DataModels.EntityKey { Id = entityId, Type = entityType },
FileNames = new List<string> { ActiveUploadFileName },
};
PlayFabDataAPI.FinalizeFileUploads(request, OnUploadSuccess, OnSharedFailure);
GlobalFileLock -= 1; // Finish SimplePutCall
}
void OnUploadSuccess(PlayFab.DataModels.FinalizeFileUploadsResponse result)
{
Debug.Log("File upload success: " + ActiveUploadFileName);
GlobalFileLock -= 1; // Finish FinalizeFileUploads
}
}
#endif

Deconstructing this example


GlobalFileLock is a very simplistic way to avoid file collisions, specifically designed for this example.
Independent file actions will not cause any issues.
Each file action requires many steps and multiple API calls, so don't try to access the same file in
multiple ways at the same time.
If you are very careful, you won't need any locking mechanism.
If you want to do something complicated, your locking mechanism may be much more complex.
OnGUI is a very old (but very dense) way to build a Unity GUI entirely within script.
Your GUI will be much better, and game-specific.
All PlayFab features first require a login or authentication.
LoadAllFiles() will do exactly as it says. For the current logged-in entity, load all file saved to PlayFab.
This requires multiple steps:
Asking PlayFab where the files are located,
And then downloading them separately.
UploadFile(string fileName) saves the file to the service for the entity.
For simplicity, this example saves one file at a time, but files can be uploaded atomically in sets as well.
The steps for this are:
Initialize an atomic upload operation,
Upload all files,
Finalize an atomic upload operation.
The entity will not consider the file upload complete, nor reflect any changes to other callers until the
atomic upload operation has been finalized successfully.

Game Manager and entities


The Game Manager allows you to manipulate objects and files for players. The player overview has been
updated to show both the title player and master player account information.

In addition, files and objects now have their own sections in the Players tab.
Use entity objects to store player data
5/24/2022 • 2 minutes to read • Edit Online

Entity objects allow you to read and write small JSON-serializable objects attached to an entity. All entity types
support the same GetObjects and SetObjects methods.
The examples that are shown below demonstrate setting and reading an Object on a title_player_account .

var data = new Dictionary<string, object>()


{
{"Health", 100},
{"Mana", 10000}
};
var dataList = new List<SetObject>()
{
new SetObject()
{
ObjectName = "PlayerData",
DataObject = data
},
// A free-tier customer may store up to 3 objects on each entity
};
PlayFabDataAPI.SetObjects(new SetObjectsRequest()
{
Entity = new EntityKey {Id = entityId, Type = entityType}, // Saved from GetEntityToken, or a specified
key created from a titlePlayerId, CharacterId, etc
Objects = dataList,
}, (setResult) => {
Debug.Log(setResult.ProfileVersion);
}, OnPlayFabError);

var getRequest = new GetObjectsRequest {Entity = new EntityKey {Id = entityId, Type = entityType}};
PlayFabDataAPI.GetObjects(getRequest,
result => { var objs = result.Objects; },
OnPlayFabError
);

Game Manager and entities


The Game Manager allows you to manipulate objects and files for players. The player overview has been
updated to show both the title player and master player account information.
In addition, files and objects now have their own sections in the Players tab.
Entities Tutorials
5/24/2022 • 2 minutes to read • Edit Online

The following tutorials show you how to use the PlayFab Entities API to enhance your coding for account and
data systems.
Available built-in Entity types
Entity API Restructure Upgrade Tutorial
Entity Groups
Entity groups
5/24/2022 • 7 minutes to read • Edit Online

PlayFab guild solution


Let's say that you need guilds, clans, corporations, companies, tribes - or whatever your game calls them -
PlayFab has them.
PlayFab builds guilds using the new Entity Programming Model, or more specifically - the entity type of groups.
Entity groups are a much broader concept than guilds, but fundamentally, entity groups have been created as a
solution for guilds.

Entity groups
Entity groups are the root concept that was inspired by the need for clans/guilds.
At its core, entity groups are any logical group of entities, which can serve any purpose. Entity groups can
simultaneously serve many purposes within your game.
Examples
Clans/Guilds - This was the starting point, and the main driving need. Entity groups can be used to
describe a set of players who are playing together on a regular basis, for whatever social glue that holds
them together on a long-term basis.
Par ties - Entity groups can be used for short-term groups created to allow individual players to
accomplish an immediate goal, and then easily disbanded afterward.
Chat Channels - Short or long term chat channels can be defined as an entity group.
In-Game subscription to information - Do you have a single-instance legendary item in your game?
Do players want constant updates about what is happening with that item? Create an entity group
focused on that item, with all player entities interested in the item as members.
In short, entity groups can be any collection of entities (whether NPC or player-controlled, real or abstract),
which need a persistent-state bound to that group.
A friends list is a group. A three person private chat is a group. Go nuts!

NOTE
We'd appreciate some warning in the forums if you are trying something we might not be expecting...

In addition, since entity groups are also entities themselves, they will contain all the initial features of entities:
Object data
File data
Profiles
They will be generally eligible for new entity features going forward, if those features are relevant to groups.

Using entity groups


Today, entity groups can contain players and/or characters. When creating a group, the first entity added to the
group is placed in an Admin role (this guide will refer to that entity as the owner, for simplicity). The owner will
then be able to invite new members, create new roles with a wide variety of customizable permissions, modify
member roles, kick members, etc.
Additionally, the same entity functions that exist for entities also function for groups, so you will be able to save
JSON objects and files directly to the group to save arbitrary game-specific data.
The code example that is provided below should give you a head start on basic guild interaction.
It allows you to create groups, add and remove members, and delete the group. It is meant to be a starting
point, and does not demonstrate any of the roles or permissions.

using PlayFab;
using PlayFab.GroupsModels;
using System;
using System.Collections.Generic;
using UnityEngine;

namespace TestGuildController
{
/// <summary>
/// Assumptions for this controller:
/// + Entities can be in multiple groups
/// - This is game specific, many games would only allow 1 group, meaning you'd have to perform some
additional checks to validate this.
/// </summary>
[Serializable]
public class GuildTestController
{
// A local cache of some bits of PlayFab data
// This cache pretty much only serves this example , and assumes that entities are uniquely
identifiable by EntityId alone, which isn't technically true. Your data cache will have to be better.
public readonly HashSet<KeyValuePair<string, string>> EntityGroupPairs = new
HashSet<KeyValuePair<string, string>>();
public readonly Dictionary<string, string> GroupNameById = new Dictionary<string, string>();

public static EntityKey EntityKeyMaker(string entityId)


{
return new EntityKey { Id = entityId };
}

private void OnSharedError(PlayFab.PlayFabError error)


{
Debug.LogError(error.GenerateErrorReport());
}

public void ListGroups(EntityKey entityKey)


{
var request = new ListMembershipRequest { Entity = entityKey };
PlayFabGroupsAPI.ListMembership(request, OnListGroups, OnSharedError);
}
private void OnListGroups(ListMembershipResponse response)
{
var prevRequest = (ListMembershipRequest)response.Request;
foreach (var pair in response.Groups)
{
GroupNameById[pair.Group.Id] = pair.GroupName;
EntityGroupPairs.Add(new KeyValuePair<string, string>(prevRequest.Entity.Id,
pair.Group.Id));
}
}

public void CreateGroup(string groupName, EntityKey entityKey)


{
// A player-controlled entity creates a new group
var request = new CreateGroupRequest { GroupName = groupName, Entity = entityKey };
PlayFabGroupsAPI.CreateGroup(request, OnCreateGroup, OnSharedError);
PlayFabGroupsAPI.CreateGroup(request, OnCreateGroup, OnSharedError);
}
private void OnCreateGroup(CreateGroupResponse response)
{
Debug.Log("Group Created: " + response.GroupName + " - " + response.Group.Id);

var prevRequest = (CreateGroupRequest)response.Request;


EntityGroupPairs.Add(new KeyValuePair<string, string>(prevRequest.Entity.Id,
response.Group.Id));
GroupNameById[response.Group.Id] = response.GroupName;
}
public void DeleteGroup(string groupId)
{
// A title, or player-controlled entity with authority to do so, decides to destroy an existing
group
var request = new DeleteGroupRequest { Group = EntityKeyMaker(groupId) };
PlayFabGroupsAPI.DeleteGroup(request, OnDeleteGroup, OnSharedError);
}
private void OnDeleteGroup(EmptyResponse response)
{
var prevRequest = (DeleteGroupRequest)response.Request;
Debug.Log("Group Deleted: " + prevRequest.Group.Id);

var temp = new HashSet<KeyValuePair<string, string>>();


foreach (var each in EntityGroupPairs)
if (each.Value != prevRequest.Group.Id)
temp.Add(each);
EntityGroupPairs.IntersectWith(temp);
GroupNameById.Remove(prevRequest.Group.Id);
}

public void InviteToGroup(string groupId, EntityKey entityKey)


{
// A player-controlled entity invites another player-controlled entity to an existing group
var request = new InviteToGroupRequest { Group = EntityKeyMaker(groupId), Entity = entityKey };
PlayFabGroupsAPI.InviteToGroup(request, OnInvite, OnSharedError);
}
public void OnInvite(InviteToGroupResponse response)
{
var prevRequest = (InviteToGroupRequest)response.Request;

// Presumably, this would be part of a separate process where the recipient reviews and accepts
the request
var request = new AcceptGroupInvitationRequest { Group = EntityKeyMaker(prevRequest.Group.Id),
Entity = prevRequest.Entity };
PlayFabGroupsAPI.AcceptGroupInvitation(request, OnAcceptInvite, OnSharedError);
}
public void OnAcceptInvite(EmptyResponse response)
{
var prevRequest = (AcceptGroupInvitationRequest)response.Request;
Debug.Log("Entity Added to Group: " + prevRequest.Entity.Id + " to " + prevRequest.Group.Id);
EntityGroupPairs.Add(new KeyValuePair<string, string>(prevRequest.Entity.Id,
prevRequest.Group.Id));
}

public void ApplyToGroup(string groupId, EntityKey entityKey)


{
// A player-controlled entity applies to join an existing group (of which they are not already a
member)
var request = new ApplyToGroupRequest { Group = EntityKeyMaker(groupId), Entity = entityKey };
PlayFabGroupsAPI.ApplyToGroup(request, OnApply, OnSharedError);
}
public void OnApply(ApplyToGroupResponse response)
{
var prevRequest = (ApplyToGroupRequest)response.Request;

// Presumably, this would be part of a separate process where the recipient reviews and accepts
the request
var request = new AcceptGroupApplicationRequest { Group = prevRequest.Group, Entity =
prevRequest.Entity };
prevRequest.Entity };
PlayFabGroupsAPI.AcceptGroupApplication(request, OnAcceptApplication, OnSharedError);
}
public void OnAcceptApplication(EmptyResponse response)
{
var prevRequest = (AcceptGroupApplicationRequest)response.Request;
Debug.Log("Entity Added to Group: " + prevRequest.Entity.Id + " to " + prevRequest.Group.Id);
}
public void KickMember(string groupId, EntityKey entityKey)
{
var request = new RemoveMembersRequest { Group = EntityKeyMaker(groupId), Members = new
List<EntityKey> { entityKey } };
PlayFabGroupsAPI.RemoveMembers(request, OnKickMembers, OnSharedError);
}
private void OnKickMembers(EmptyResponse response)
{
var prevRequest= (RemoveMembersRequest)response.Request;

Debug.Log("Entity kicked from Group: " + prevRequest.Members[0].Id + " to " +


prevRequest.Group.Id);
EntityGroupPairs.Remove(new KeyValuePair<string, string>(prevRequest.Members[0].Id,
prevRequest.Group.Id));
}
}
}

Deconstructing the example


This example is built as a controller, which saves minimal data to a local cache (PlayFab being the authoritative
data layer), and provides a way to perform CRUD operations on groups.
Let's take a look at some of the functions in the example provided:
OnSharedError - This is a typical pattern with PlayFab examples. The simplest way to handle an error is to
report it. Your game client will probably have much more sophisticated error handling logic.
ListMembership - This calls ListMembership to determine all the groups that the given entity belongs to.
Players will want to know the groups they have already joined.
CreateGroup / DeleteGroup - Mostly self-explanatory. This example demonstrates updating the local
group info cache when these calls are executed successfully.
InviteToGroup / ApplyToGroup - Joining a group is a two-step process, and it can be activated both
directions:
A player can ask to join a group.
A group can invite a player.
AcceptGroupInvitation / AcceptGroupApplication - The second step of the join process. The responding
entity accepts the invitation, completing the process of making the player a part of the group.
RemoveMembers - Members with authority to do so (defined by their role permissions), will be able to kick
members from a group.

Server vs client
Like all new entity API methods, there is no distinction between the server API and the client API.
The action is performed by the caller, according to how the process was authenticated. A client will be identified
as such, and will call these methods as a title player entity, and their roles and permissions within the group will
be evaluated with every call, ensuring they have permission to perform this action.
A server is authenticated with the same developerSecretKey , which identifies that process as a title entity. A title
will bypass the role checks, and API calls executed by a title will only fail if the action is impossible to perform, in
an instance such as if an entity cannot be removed if they are not a member.
Entity API restructure upgrade tutorial
5/24/2022 • 2 minutes to read • Edit Online

Introduction
We have restructured the APIs that were lumped under the Entity API group into coherent logical groups that
make their consumption easier, both via the documentation site, and the PlayFab SDKs.
The immediate impact is that if you have been using the entity-based APIs in your game, the code will need to
be updated when you upgrade your SDKs.

Prerequisites
The following conditions must be true for this upgrade guide to apply to you:
1. You are using the entity-based PlayFab APIs.
2. You have upgraded to a PlayFab SDK, published on 8/9/2018 or later.

NOTE
There are no service level changes. For example, existing titles using old SDKs will work without requiring changes.

How to upgrade
The fundamental impact of this change is that the PlayFabEntityModel API group has been separated out into six
different API groups that are logically bound together, as shown in the following picture.
A full list of Previous Entity API -> New API mapping can be found in APPENDIX 1 of this tutorial.

NOTE
The Classic API mapping has not been affected.

The next section will walk you through an example of upgrading a C# SDK using the PlayFabEntityAPIGroup to
the new set of API groups.

Upgrade example: C# SDK


Please follow these steps to upgrade your application.
Step 1 : Change any using statements that reference PlayFab.EntityModels such as those shown below.

using PlayFab.EntityModels;
using PlayFab.DataModels;

You can now be granular in your selection of which of these APIs you want to bring in, instead of importing the
whole Entity API group.
Step 2 : A more in-depth coding example of the New API, with comments in regard to how it looked before is
provided below.

public async void Example()


{
var logrequest = new PlayFab.ClientModels.LoginWithCustomIDRequest
{
CustomId = "TestExample",
CreateAccount = true,
};

var loginResult = await PlayFab.PlayFabClientAPI.LoginWithCustomIDAsync(logrequest);


var playfabId = loginResult?.Result?.PlayFabId;

// PlayFab EntityAPI has been replaced here with the PlayFabProfilesAPI


// and PlayFab.EntityModels has been replaced with PlayFab.ProfileModels
var getProfileResult = await PlayFab.PlayFabProfilesAPI.GetProfileAsync(new
PlayFab.ProfilesModels.GetEntityProfileRequest());
var profile = getProfileResult?.Result?.Profile;
}

Please follow suit for other SDKs, using the mapping from APPENDIX 1 in this tutorial.

Conclusion
We’re excited to expose the Entity APIs in a more intuitive way on our documentation site and in our code, based
on your feedback.
If you have any questions and comments, please contact us via the PlayFab Forums.

APPENDIX 1: OLD to NEW API mappings


All of the APIs listed below were previously part of the PlayFabEntityModel API group. They are now categorized
under the following new API groups.
PlayFabProfilesApi
GetGlobalPolicy
GetProfile
GetProfiles
SetGlobalPolicy
SetProfilePolicy
PlayFabAuthenticationApi
GetEntityToken
PlayFabDataApi
AbortFileUploads
DeleteFiles
FinalizeFileUploads
GetFiles
InitiateFileUploads
GetObjects
SetObjects
PlayFabGroupsApi
AcceptGroupApplication
AcceptGroupInvitation
AddMembers
ApplyToGroup
BlockEntity
ChangeMemberRole
CreateGroup
CreateRole
DeleteGroup
DeleteRole
GetEntityToken
GetGroup
InviteToGroup
IsMember
ListGroupApplications
ListGroupBlocks
ListGroupInvitations
ListGroupMembers
ListMembershipOpportunities
RemoveGroupApplication
RemoveGroupInvitation
RemoveMembers
UnblockEntity
UpdateGroup
UpdateRole
PlayFabEventsApi
WriteEvents
PlayFabCloudScriptApi
ExecuteEntityCloudScript
Data Connections
5/24/2022 • 3 minutes to read • Edit Online

Data Connections enables the continuous near real-time distribution and ingestion of PlayStream and
Telemetry data into your chosen and authorized storage resource in your Azure subscription, such as Azure Blob
Store.
It provides control of your data in your storage account with less than 5-minute data ingestion latency. The
architecture is designed for better batch processing that facilitates Parquet files in blob storage with the highest
throughput, low storage cost, and most flexibility.
You can configure up to three Azure blob storage accounts in the WestUS2 region. In case of failure in data
distribution, a built-in automatic retry mechanism is in place to ensure data quality.
You can get started with Data Connections for event ingestion using PlayFab’s Game Manager portal or scalable
APIs.

Why do you need it?


Data Connections is the replacement for the Event Export and Export to S3 features that currently PlayFab
supports. Data Connections allow for faster export in preferred formats for offline processing. You get to bring
your storage account for data to be ingested and distributed. That means you get to manage and control the
encryption-at-rest policy, the lifetime management policy, and network access. The billing becomes simplified as
the costs associated with that storage account are accounted for centrally in your all-up Azure account billing.
The data is readily available in Parquet blob format. Parquet is a column-oriented data file format designed for
efficient data storage and retrieval. It provides efficient data compression and encoding schemes with enhanced
performance to handle complex data in bulk, resulting in low latency, higher throughput, and low cost of data
storage. It's designed to be a common interchange format for both batch and interactive workloads. Thus, Data
Connections enables your endeavors for custom advanced analytics and reporting, to run ad-hoc queries in a
cost-optimized manner.
For more optimized cost and data control, you can make use of Data Connections with Event Sampling -
Sampling enables you to configure the percentage of events data that you want to receive.
Grant PlayFab access to your storage container
For Data Connections, you need an Azure subscription and a storage account.
For existing PlayFab and Azure customers, you can create a storage container on the Azure portal and get
started with Data Connections on Azure PlayFab.
For existing PlayFab who are new to Azure, you can sign up for an Azure subscription.

NOTE
Make sure to create your Storage Account in the West US 2, otherwise, egress cost will be applied to your storage
account.

For PlayFab to ingest data in your storage account, container details along with authorization using a SAS token
are required. To create a SAS token using the Microsoft Azure portal, follow the steps below.
Option 1: Create the SAS token on the container level.

IMPORTANT
Generate and retrieve the shared access signature for your container, not for the storage account itself.

In the Azure portal, select Your storage account > Containers .


Select a container from the list.
Go to the right of the main window and select the three ellipses associated with your chosen container.
Select Generate SAS from the dropdown menu to open the Generate SAS window.

Define Permissions by selecting or clearing the appropriate checkbox. Make sure the Create and Write
permissions are selected.
Specify the signed key Star t and Expir y times.
Select Generate SAS token and URL .
The Blob SAS token query string appears in the lower area of the window.
Copy and paste the Blob SAS token values into a secure location for use in the Azure PlayFab Data
Connections . It's displayed only once and can't be retrieved after the window is closed.
Option 2: Create the SAS token on the account level.
IMPORTANT
Generate and retrieve the shared access signature for your storage account itself.

In the Azure portal, select Your storage account


Select a Shared access signature from the list under Security + Networking .
Define Ser vices by selecting blob and clearing other checkboxes.
Define Resource Type by selecting Object and clearing other checkboxes.
Make sure the Create and Write permissions are selected.
Specify the signed key Star t and Expir y times.
Select Generate SAS token and URL .
The Blob SAS token query string appears in the lower area of the window.
Copy and paste the Blob SAS token values into a secure location for use in the Azure PlayFab Data
Connections . It's displayed only once and can't be retrieved after the window is closed.
Data Connections quickstart
5/24/2022 • 2 minutes to read • Edit Online

Pre-requisite:
For Data Connections, you need an Azure subscription and a storage account.
For PlayFab to ingest data in your storage account, container details along with authorization using a SAS
token are required. To create a SAS token using Microsoft Azure portal, follow the steps below.

IMPORTANT
Make sure to create your Storage Account in the West US 2, otherwise, egress cost will be applied to your storage
account.

Create a Data Connection


A Connection is created to integrate your storage resource with PlayFab and retrieve the PlayStream and
Telemetry data. You can configure up to three data connections in the “enabled (active)” state. From the Game
Manager:
Navigate to your Title
Select Data from the menu on the left
Select Data Connections from the Data tabs
Select New Connection , new data connections configuration page is opened
Define Sink Setting of Azure Blob Storage type
Enter Name
Enter Account Name
Enter Container Name
Enter SAS Token as generated in the Azure portal
Select Save
With the default check on Enabled , the connection between PlayFab and the customer’s resource is
established once saved.
With uncheck on Enabled , the connection between PlayFab and the customer’s resource is validated
but not established until saved.
Manage Connections
The Data Connections overview (landing) page displays the available connections categorized as enabled or
disabled as a status . You can have up to 3 enabled connections to the blob storage account at any time. The
Data Connections overview page can also be used to manage connections by selecting any Connections’ ellipsis
(…). Two actions comprising Edit and Delete can be taken on the connections.
Manage Events
5/24/2022 • 2 minutes to read • Edit Online

Overview
PlayFab Manage Events feature helps you configure the percentage of events data that you want to receive in
the title tenant database. By default, all PlayStream and Telemetry (custom) events are stored. However, in some
situations, you might want to retrieve only a sample set of events. To achieve that, use Manage Events with
Sampling rate.
Benefits of Manage Events
Sampling leads to a reduction of the volume of the total event, particularly benefitting you with below in a
controlled and flexible manner:
Reduced cost of storage on your title tenant database
Increased performance of event searches
Easy data exploration to determine the characteristics of a large data set
Uncompromised validation of the data format, statistical calculations, and other analysis without any loss of
data fidelity
Sampling Ratio
The sampling ratio is the probability percentage of any event being included in the sample result set. It ranges
from 0% to 100%. By default, event sampling isn't active, meaning the sampling rate is set to 100%, and every
event of the title is ingested and stored into the title tenant database.

Data Analysis on Sampled Data


For statistical true data analysis, examined the data by ensuring a correlated scale as of the sampling rate of the
event(s).
When you calculate statistics using a sample set of events, the statistical values won't be accurate. To get the
most accurate statistical value approximation, you must scale the values to the corelated sampling ratio. Because
when you use sampling, the returned set isn't the complete set of all of the events.
NOTE
Commands for statistical calculations that might be difficult to interpret when event sampling is used, like count,
summarize, max, min, and more.
Event Sampling quickstart
5/24/2022 • 2 minutes to read • Edit Online

To take advantage of sampling using our Manage Events page, configure a sampling percentage on individual
event levels. When you specify a sampling percentage on a certain event, sampling comes into effect by
overriding the default or existing value and remains in effect until you change it. The percentage specified in the
sample ratio field is the percentage of events that will be filtered out.
The sampling rate can be as high as 100% and as low as 0%. By default, the sampling rate for all events is 100%,
thus, leading to 100% event retention in the sample set.

NOTE
Sampling comes into play after all the events are processed by the PlayStream rules engine. So, all events will support
actions/ rules, if specified and independent of sampling.

Configure Sampling for Event(s)


You can configure the sampling ratio on both PlayStream and Custom events from the Game Manager portal. To
do so,
Add Sample Rate to an Event
Navigate to your Title
Select Data from the menu on the left
Select Manage Events from the menu on the left
To add sample rate for an intended event, determine if it’s a PlayStream or Telemetry event. Based on it,
Select the Event Namespace from the drop-down of the Add Sample Rate windowpane
Then, select the Event Name from the drop-down
The Event Name dropdown contains the comprehensive list of events that are applicable for
event sampling and are yet to have any sampling configuration
Enter a whole number as the desired Sample Rate which ranges between 0% to 100%
Select Save , the event sampling is configured
The configured event will show up in a new pane known as Sampled Events , just above the Add
Sample Rate pane
The Sampled Events overview pane shows all the configured Event Name with a
categorization of Event Namespace , Categor y stating if it’s a standard PlayStream event or
custom event, along with the configured Sample Rate
NOTE
Sampling takes up to 4 hours to come into effect and processes the configuration on each event level.

Manage Sample Rate to an Event


The overview (landing) page displays the sampled events pane. You can manage events by selecting the
Sample Rate box and modifying it as desired . The options to modify appear on hover over any event. To
persist the change, select save button, and to revert the change, select the cancel button.
To remove the sampling for any sampled event(s), modify the Sample Rate box with a 100% entry and select
the persist button.
Content Delivery Network (CDN)
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
PlayFab CDN is a legacy feature supported for accounts with at least one title that has previously configured CDN. For
new PlayFab developers interested in a content management solution, we recommend using Azure CDN. To get started,
see the Azure CDN documentation.

The Content Delivery Network (CDN) is an infrastructure used to deliver assets - such as images, audio, binary
content, etc. - to the end user that focuses on speed and availability.

Pricing
CDN costs are independent of your pricing tier (Essentials, Professional, etc.), and require that you have an active
PlayFab payment account. CDN has one key meter, Egress , which is billed at $0.10 per GB.

View cost and usage report


To locate the cost of CDN, navigate to the Title Over view page, select Content from the left navigation menu,
and then select File Management from the list of tabs. The cost is located at the top of the File Management
page. CDN costs are calculated based on the number of downloaded gigabytes per title during the billing period.
To view daily content usage, select the Usage Repor t button in the upper right, which will navigate to the
Reports page. Select a specific report to see visualizations of the data or download a CSV.

Links
Content Delivery network quickstart
Content Delivery Network quickstart
5/24/2022 • 3 minutes to read • Edit Online

IMPORTANT
PlayFab CDN is a legacy feature supported for accounts with at least one title that has previously configured CDN. For
new PlayFab developers interested in a content management solution, we recommend using Azure CDN. To get started,
see the Azure CDN documentation.

The PlayFab Content Delivery Network (CDN) stores individual assets as files uniquely identified by the file
name (also referred to as a key). This implies that you add, update, remove, and retrieve assets by key.
PlayFab CDN allows segregating assets by folders. The folder path to the asset becomes part of the asset key.
The following example is a valid asset key stored inside the folder named Android .
Android/Image.png .
When the user is fetching assets, their requests are automatically routed to the nearest edge location, so content
is delivered with the best possible performance.
This, however, can introduce delays into file management actions, like those found in the following examples:
File uploading : Your file will be available immediately.
File over writing : The old file will appear to users for up to 24 hours, until it's overwritten with the new
file.
File deletion : The file will continue to exist for up to 24 hours, while the delete command removes it
from all edge locations.

Uploading assets
Before your users are able to fetch an asset, it must be uploaded to the CDN. This can be done in Game
Manager :
Select Content from the menu on the left.
Choose the File Management tab.
Then select the Upload Files .
You may:
Select multiple Files (1) .
Every file selected will appear in the list (2) .
Submit your files by selecting the Upload Files button (3) .

Uploaded files will appear in the list (1) .


Keep in mind that you may also manage folders.
To create a folder, select the New Folder button (2) .
Fill in the Folder name (1) .
Select the Create Folder button (2) .
This will create a new folder in the tree. You may then select this folder, and upload the files normally.
Alternatively, you may upload assets via code using the admin SDK. This is a two step process:
1. First, call GetContentUploadUrl and obtain the pre-signed URL that will authorize your upload.
2. Then, use the URL to make a HTTP PUT request, provide your data, and (optionally) content type.
Consider using the snippet provided below that shows how to get a pre-signed URL.

public void UploadFileToCDN(string key, byte[] content, string contentType = "binary/octet-stream") {


GetUploadUrl(key, contentType, presignedUrl => {
PutFile(presignedUrl, content, contentType);
});
}

void GetUploadUrl(string key, string contentType, Action<string> onComplete) {


PlayFabAdminAPI.GetContentUploadUrl(new GetContentUploadUrlRequest() {
ContentType = contentType,
Key = key
}, result => onComplete(result.URL),
error => Debug.LogError(error.GenerateErrorReport()));
}

void PutFile(string presignedUrl, byte[] content, string contentType = "binary/octet-stream") {


// Implement your own PUT HTTP request here.
// - Must use PUT method
// - Must set content type Header
}

You may then check the result through the PlayFab Game Manager. Make sure the file is in the list.

Fetching assets
Downloading the asset via code is identical to uploading the asset. As wwe mentioned earlier, it is a two step
process.
1. First, make a call to GetContentDownloadUrl and obtain a pre-signed URL that will authorize your download.
2. You then use the pre-signed URL to make a HTTP GET request, and fetch the data.

Consider using the snippet provided below that shows the bare bones of the process.
public void DownloadFileFromCDN(string key) {
GetDownloadUrl(key, presignedUrl =>
{
GetFile(presignedUrl);
});
}

void GetDownloadUrl(string key, Action<string> onComplete) {


PlayFabClientAPI.GetContentDownloadUrl(new GetContentDownloadUrlRequest() {
Key = key,
ThruCDN = true
}, result => onComplete(result.URL),
error => Debug.LogError(error.GenerateErrorReport()));
}

void GetFile(string preauthorizedUrl) {


// Implement your own GET HTTP request here.
}

As mentioned above, CDN may involve latency in regards to file updates. During development, it is sometimes
useful to force-fetch the latest, freshest files.
The GetContentDownloadUrl call allows you to set the ThruCDN parameter to False . The URL returned will then
point to non-cached fresh files.

NOTE
Your published game client should never use this option!
Webhooks
5/24/2022 • 2 minutes to read • Edit Online

In complex systems, you may want to provide additional event handling on your custom server. To achieve this,
PlayFab offers Webhooks.
Whenever a new event is emitted, it can be forwarded to your server by making a POST request to your custom
web endpoint. The event data is then passed as the JSON body of the request.

IMPORTANT
Entity PlayStream Events do not currently support forwarding with Webhooks.

Accessing Webhooks
To access the Webhooks panel in the PlayFab Game Manager screen:
1. Select Data in the sidebar menu.
2. Then choose the Webhooks tab.

Overview of the Webhooks panel


The image shown below provides an overview of the Webhooks panel.
1. The New Webhook button allows you to create and configure a new Webhook.
2. The Webhook Name area can be used to access and configure the Webhook.
3. The Status area shows whether a Webhook is currently enabled .
4. The Failing Since area shows when a Webhook endpoint stopped returning OK responses.
5. When one or more Webhooks are selected, you can use the Delete button to permanently remove them.

Configuring a Webhook
The image shown below describes the options for configuring a Webhook.
1. Use the Name field to create a Webhook name that will uniquely identify the Webhook.
2. Set up the Endpoint URI . This URI will be hit when the Event occurs.
3. You may set the Webhook as Enabled - true or false . This allows you to temporarily suspend a Webhook
without completely removing (deleting) it from the system.
4. You may set the option to Post multiple events in JSON array if you want to have multiple events posted
to your service in an array. If you select this option your service must be able to handle both multiple and
single events.
5. You can add up to three request headers and the value of those headers. This allows you to post headers in a
secure way to services such as Azure Event Hubs, Azure Functions, Google Functions and Amazon Lambda.

NOTE
The request header keys can be up to 64 characters and the values can be up to 256 characters for each header.

1. Set up the Filters to only process the Events you need. You can filter by Event Name , Event Source , and
PlayerID .

NOTE
You can have several Filters per Group , but each Filter setting must be matched for the event to fall into the Filter
Group .

1. You may define several Filter Groups to include different filters. Events must fall into at least one group to
be passed to the Webhook.
What is PlayFab Analytics?
5/24/2022 • 2 minutes to read • Edit Online

PlayFab Analytics is a set of tools for data analytics, storage, processing, and exports. The features included are
Experiments, Metrics, Reports, and Segmentation.
Segmentation lets you create groups of players based on their player properties. Players will move in and out of
segments in real-time, as Playstream events occur. Segmentation can be integrated with many other services
across PlayFab. To get started, see the Segmentation Quickstart.
Experiments allows you to create and manage multiple concurrent experiments through Game Manager.
Experiments can be scheduled to run at certain times, and run across targeted player segments. To get started,
see the Experiments Quickstart.
Metrics automatically calculates a daily report of industry-standard metrics on engagement and revenue.
Explore your metrics in the Reports and Trends tabs of the Dashboards section in Game Manager. To get started,
see the Metrics Quickstart.
Reports automatically generates daily, monthly, and 30-day rolling views for engagement and monetization. To
get started, see the Reports Quickstart.
Experiments
5/24/2022 • 3 minutes to read • Edit Online

Overview
PlayFab Experiments feature helps you identify the best strategies for your game. It does so by helping you run
multiple concurrent experiments and ensure statistical trustworthiness.
You can elevate the player experience by comparing different versions of game configurations, pricing models,
and outreach mechanisms, determining the best variation for your title’s goals (engagement, monetization,
retention, etc.) via experiments.
Capabilities of PlayFab's Experiments
PlayFab Experiments is a tailored solution for running experiments in your games. It is powered by Microsoft's
internal experimentation platform which unlocks the best-in-class capabilities which are used by Minecraft,
Azure, Office, Bing, and many other Microsoft products. PlayFab Experiments empowers you by providing the
following capabilities:
Creation and management of multiple concurrent experiments with the (interactive and self-directing) user
interface on PlayFab Game Manager and via scalable APIs.
Targeting of the desired audience at random but in a controlled manner by making use of existing traffic. You
can experiment over a segment and define the percentage of the target audience in each variant.
Scheduling of experiments or to run immediately.
Analysis of experiments' scorecard results. The scorecards are computed reliably and possess enriched
statistical details. This gives you an indication of statistical significance and alerts if a Sample Ratio Mismatch
is observed.
Integrability with other PlayFab services such as Title Data, Player Profile, PlayStream events, CloudScript and
Insights Explorer, etc.
Experiment Configurations using PlayFab’s Experiments Variants
The experiment compares the game configurations, be it the in-game experience, or the other game growth
strategy. These configurations can be enabled through a game code and mapped to the variant-variable pair or
variant-override pair. Each configuration is easily mappable to variants of an experiment to enable any game
experience.
A control experience is mapped to a control variant and is compared against one or more treatment experience
mapped to a treatment variant to study the player behavior and determine which variant experience or
configuration works better.
Game Configurations mapped to Variables (Requiring no new code deployment)
Each configuration is easily mappable to variants where each variant is supported by variables. These
variables allow you to bundle a different set of game experiences via parameterization.
Overrides as Game Configuration (Requiring no game code change)
Game configuration using PlayFab services can be experimented using Overrides without adding any extra
code.
Overrides are subsets of configuration which contain modifications to the default title data, that can be used
as variants in Experimentation. Currently, experiments with overrides are only available when using Title
Data.
Configurations involving Title Data are a set of key-value pairs that are ideal for storing and managing
the game’s remote configuration on the server. It keeps the title wide configuration variables
accessible and organized which can be retrieved on the client-side.

NOTE
For concurrent experiments using overrides, it is recommended to experiment on a mutually exclusive target audience.
This will ensure the correct assignment of overriding configuration and no interaction on the client-side. Thus, resulting in
statistically correct experiment design and thereby analysis results.

PlayFab Experiments at a Glance

PlayFab Experiments enables you to run multiple concurrent randomized experiments in a managed and
controlled manner. In the process,
A unique identifier for each running experiment's variant groups called a variant ID is tagged to each player
profile. These variant IDs are assigned to different treatments via client or server-side code. Thus,
instrumenting different treatment behaviour.
Each variant group is supported and defined by variables. These variables are attributes on variant groups
that allow you to bundle a different set of game experience via parameterization.
Reliable computation of results of an experiment with statistical significance calculation is provided.
Detection of issues when the targeted audience traffic is way off. This is often caused by a treatment causing
crashes or affecting logging. PlayFab's experimentation feature flags such issues enabling you to run a
reliable experiment.
Quick Start
5/24/2022 • 7 minutes to read • Edit Online

Create an Experiment
An experiment is created to compare a control variant against one or more treatment variants (up to 9). The
experiment is managed through a target audience controlled by the user.
From the Game Manager:
Navigate to your Title
Select Experiments from the menu on the left
Select New Experiment , experiment configuration page is opened
Enter Experiment Name , Description , Star t Date & Time , Duration (up to 90 days)
Select your target Audience for the experiment. By default, the experiment's audience is “Run across all
title players”
Configure to run the experiment on a Segment by selecting the radio button “Select player segment” and
select on the drop-down
(Optional) Under Exclusion Group , select exclusion group from the drop-down list of the existing
Exclusion group name and enter % traffic allocationto , to run a mutually exclusive experiment
Under Variants , define the Control Variant and Treatment Variant(s)
Enter Variant name and Description
Each variant is supported and defined by Variables (up to 10) and Overrides
The variables are attributes on variant groups that allow you to bundle different sets of user-
experience via parameterization
This variable parametrization configures the feature settings for variants without deploying
new code. This allows you to iterate faster on changes and make fixes and updates to live
games. It is recommended to have the same variable name in each of the variant group as part
of best practices of experimentation
The overrides are attributes on variant groups that allow you to bundle different sets of
configurations of PlayFab services via parameterization, i.e., no game code is required.
Currently, overrides are available for title data remote configuration service only
Each variant is associated with the % of target audience . For a controlled experiment, it determines
the traffic stream and instrumentation of variants
Sufficient traffic is required to make the changes from your experiments more detectable. An
experiment with equal traffic in each variant will have the best ability to detect a change
For concurrent experiments using overrides, it is recommended to experiment on a mutually
exclusive target audience
Select Schedule , Save as Draft , or Run Now
With Schedule, the experiment will be in Scheduled status in the experiments overview and timeline
page
With Save as Draft, the experiment will be in the Draft status in the experiments overview and
timeline page
With Run Now, the experiment will be in Running status in the experiments overview and timeline
page
Manage Experiments
The Experiments’ overview (landing) page displays the available experiments categorized based on the status,
which is Running , Scheduled , Drafted , Completed .
The Running and Scheduled experiments are shown in a timeline view. Here the high-level details on each
experiment are available, like the experiment's Name , number of Variants , Star t Date & Time , End Date &
Time . Interestingly, for an experiment in running state, one can also see a near-real-time metric of Player
Count which gives insights into the number of players that have been assigned to the experiment in the last 8
hours.
The Drafted experiments are shown in the same ‘In-progress’ tab. Just below the timeline card view.
The Completed experiments after their run completion are shown in the ‘Completed’ tab with details of the
experiment's Name , number of Variants , Star t Date & Time , End Date & Time .
The Experiments page can also be used to manage experiments by selecting on any experiments’ ellipsis.
Here,
A scheduled experiment is automatically picked to run based on the configured schedule
The configuration's variations mapped in each variant of the experiment is enabled to the qualifying traffic
immediately at random
A previously scheduled experiment can be started at any time before its start date, just select the ellipsis of
the intended experiment from the list of scheduled experiments and Select Run. Different actions can be
taken on experiments based on their state, and the action set comprises of Run , Stop , Clone as draft . More
precisely like,
Stop and Clone as draft of a running experiment
Run, Delete and Clone as draft of a scheduled experiment
Delete of a drafted experiment
Delete and Clone of a stopped/ completed experiment
Note: One can also Clone an existing experiment from the experiment's edit configuration page which allows
further edits
A scheduled and drafted experiment's fields are completely modifiable and vice-versa for a stopped/
completed experiment. Select on the ellipsis to make Edit . Although, for any experiment in running state,
only Experiment description and duration modifications are possible
A running experiment status is turns Completed , once the duration of the experiment is reached or a user
explicitly stops the experiment

Analyze Experiment
Experiments' results are shown in Experiment details and scorecard page . The scorecard is generated in a
regular cadence. The first scorecard is generated in 12 hours, followed by scorecard(s) every 24 hours for the
entire duration of an experiment.
Once the experiment is completed, select the Completed tab view, and select on the name of the experiment to
view the Scorecard , along with the experiment details. Additionally, the at-run experiments’ scorecard and
details can be viewed by selecting the name of the experiment.
The Experiment details and scorecard page lists the experiment name, description, start and end date, intended
duration, audience, and variant count. The actions like Stop, Run, Clone as draft is available on the page based on
the state of the experiment.

NOTE
To learn more about SRM and how to resolve it, see the Sample Ratio Mismatch section in Experimentation Best
Practices and Recommendations)
For details on the variant, its associated variables, and overrides, select Configuration and Experiment
configuration page will be displayed with details.
At the completion of the experiment:
The overall statistical computation of each metric is available for analysis.
At the experiment run:
If an issue of Sample Ratio Mismatch (SRM) is identified, then it is flagged to the user for investigation.
SRM indicates sampling bias in the randomization which leads to the options of resolving bugs (if any),
immediately stop the experiment based on the estimated impact or take the risk and let the experiment to
continue.
Scorecard Metrics
PlayFab has pre-identified a set of simple, effective, and actionable metrics for analysis of experiment results.
These are tracked and categorized to measure impact on the acquisition, activation, retention, and revenue of
the title. These are computed based on the player_logged_in and player_realmoney_purchase events.
The identified metrics are calculated for the time the experiment has ran so far based on the configured
duration. The metrics are:

TYPE M ET RIC DESC RIP T IO N

Acquisition Average Login Per User Average of all user logins

Activation Payer Conversion Rate Percentage of active users who


purchased

Revenue Average Revenue Per User Average of revenue generated from


users including those that didn't make
any purchase

Retention Day N Retention (N = 1, 2, 3, 5, 7, 14, Percentage of users who logged in N


21 day) days after seeing the experiment

Experimentation APIs
PlayFab has scalable and integrable APIs for experimentation. The APIs and associated operation details are as
below:

API NAME O P ERAT IO N


API NAME O P ERAT IO N

Create Experiment Allows a client to request the creation of an experiment for


the title. The experiment configuration gets defined as part
of it, containing the experiment details, like target audience,
start date, variant groups, and associated variables for
orchestrating the change in experience (or treatment
assignment). The treatment assignment can include virtually
anything on the client or PlayFab services.

Update Experiment Allows a client to request an update in the experiment


configuration of an existing experiment for the title based on
the experimentation ID.

Star t Experiment Allows a client to request the start of an existing experiment


for the title based on the experiment ID. The client code gets
orchestrated for the change in experience as per the
treatment assignment given for the experimental study on
the target audience.

Stop Experiment Allows a client to request the stop of an existing running


experiment for the title based on the experiment ID. The
default client code (control variant) gets orchestrated for the
change in experience for the entire audience.

Delete Experiment Allows a client to request a delete of an experiment in


completed/stopped status for the title based on the
experiment ID.

Get Experiments Lists all the experiments and its details, no matter which
state (drafted, running, and completed/stopped) for the title.

Get Treatment Assignment List the treatment assignments for a player for every
running experiment in the title.

Get Latest Scorecard Gives the latest scorecard result for an experiment of the
title.

NOTE
For more information about the Experiments APIs, see Experimentation APIs.

Integrating Experiments with other PlayFab services


Experiments is compatible with Player Profile, PlayStream events, CloudScript and Insights Explorer. For example,
you can:
Make configuration changes using CloudScript: Virtually any configuration-related game code
variation can be enabled using a combination of CloudScript and Experiment's getTreatmentAssignment API.
Make configuration changes using PlayStream events: Use the getTreatmentAssignment API to trigger
game configuration changes based on PlayStream events.
Do a drill-down analysis using Insights Explorer : A unique identifier of each variant (VariantID) is
stamped on all PlayStream v2 events and two specific PlayStream v1 events (player_logged_in and
player_realmoney_purchase). This can be used to do further analysis on specific metrics. (The metrics can be
based on the PlayStream events or your own game telemetry.) To query, use the Insights Explorer service or
connect your own analytics platform.

WARNING
A new player login only has attributes associated with the player_logged_in PlayStream event. An experiment that targets
a new player with PlayStream event-based configuration variations can only use attributes that are part of the
player_logged_in PlayStream event. This ensures treatment assignment to the new players who have no PlayStream
events associated yet.
Prevent Interaction Effects with Exclusion Group
5/24/2022 • 3 minutes to read • Edit Online

For related concurrent experiments, it is important for players to only see one of the experiments in order to
prevent skewed results. This is where exclusion groups come into play. PlayFab exclusion groups allow you to
create mutually exclusive experiments.
With an exclusion group, you limit the participating target audience (players) to participate in one experiment at
a time. This ensures that the same users don't see overlapping experiments within an exclusion group. This
means that the data collected for one experiment is not affected by any other experiment, even if both the
experiments are set up on the same game flow and targets the same set of players.
In an exclusion group, the traffic allocation happens without overlapping players’ data between the experiments
and is distributed at random in different buckets of players for each experiment. This ensures clean results
where the change in conversion rate is attributed to the correct experiment without bias and overlap of the
target audience, eliminating any interaction effects.
For unrelated experiments, it does not matter if your players become a part of more than one experiment.
However, if the experiments are related like below, with concurrent or overlapping run schedule, you may want
to keep the players exclusive to each experiment:
Variation of configurations on the same game flow
Variation of configuration involving the same funnel where there is a possibility of player overlap
Please note, use of exclusion group reduces the statistical power of your experiments as each one competes with
others for traffic. So, use exclsuion group when experiments are related and interaction effects are anticipated.
You can create experiment(s) with exclusion group(s) through Game Manager and APIs.

Create Exclusion Group


From the Game Manager:
Navigate to your Title
Select Experiments from the menu on the left
Select Experiment Settings on the right side of the page, the settings page opens
Under Exclusion Group, select Add exclusion group
Enter the Name and Description for the group, and select Save
This navigates to the exclusion group overview page which shows the details of exclusion groups along with the
Available traffic % and Experiments in each of them. You can edit and delete any exclusion group. Please
note, if certain experiment(s) is running within an exclusion group then that exclusion group is undeletable until
the run completion of the experiment(s) under it.
Create Experiment with Exclusion Group
From the Game Manager’s Experiments page:
Select New Experiment , experiment configuration page opens
Enter Experiment configuration details like Experiment Name , Description , Star t Date & Time ,
Duration (up to 90 days)
Select your target Audience for the experiment. By default, the experiment's audience is “Run across all
title players ”. Configure to run the experiment on a Segment by selecting the radio button “Select player
segment ” and select on the drop-down
To run a mutually exclusive experiment, configure under Exclusion Group by selecting the button “Add
exclusion group ”
Select exclusion group from the drop-down list of the existing Exclusion group name
Enter % traffic allocation which is the percentage of total traffic that is eligible for the experiment
If the % traffic allocation is greater than the Available traffic % then scheduling or immediate
run of the experiment will not persist
Under Variants , define the Control Variant and Treatment Variant(s)
Select Schedule , Save as Draft , or Run Now
Management of Experiments with Exclusion Group
The Experiments’ overview (landing) page displays the available experiments. The Running and Scheduled
experiments are shown in a timeline view. The Drafted experiments are shown in the same ‘In-progress’ tab.,
just below the timeline card view.
The exclusion group and associated traffic are editable for Schedules and Drafted experiments. The caveat is
that only if the available traffic % exists the change in experiments’ exclusion group configuration will persist.
Experiments Recap
5/24/2022 • 9 minutes to read • Edit Online

This guide introduces you to the practice of experimentation. It details why you should experiment early, best
practice recommendations, and provides information to help your become comfortable with the process.

Reasons experiment matters


Experiments are the gold standard for identifying the effects of game experience changes. If you understand the
effects of game experience changes, and have data to back it up, it is easier to make decision that allow you, to
craft more effective game design, experiences, and marketing strategies. Continual experimentation enables you
to determine if the effectiveness of your changes diminish over time.
Regardless of what stage of game development journey (creation or operation) you’re on, PlayFab Experiments
allows individuals, teams, and studios to make careful changes to the game experiences while collecting
empirical data which in-turn helps you figure out exactly what works best for the game.
Experiments are an effective practice that gives you insights into a gamer’s behavior in a controlled and limited
audience (player traffic). Thus, protecting your player base from an unsatisfactory game experience. Also, you
can make better use of the resources and easily enable or disable game features in a live game.Experiments
helps you transform from “we think” to “we know” decision making power. It is an effective practice which gives
you insights into gamer’s behavior with controlled and limited audience (player traffic). Thus, protecting your
player base from repulsive game experience. Also, one can make better use of the resources and easily enable/
disable game features in a live game.
Here are some common goals for game studios when experimenting:
Increased Active Player Base
Higher Conversion Rate
Lower Churn Rate

Experiment's trustworthiness is Important


When you make decisions based on the results of experiments that you are running, you will want to make sure
that a relationship/ causation exists. An experiment's trustworthiness is equated by the statistical significance of
the experiment results.
Trustworthiness is the focus of PlayFab's experiment results. All metrics are checked for statistical significance.
For example, if you run an experiment that measures a 2% lift in retention and it is shown as statistically
significant with a p-value of 0.04, that means there is 4% chance that a result of 2% or greater would have been
observed assuming there was no difference between A and B (i.e., assuming the null hypothesis is true). The true
difference is not directly measurable, and statistics are used to get a reasonable estimate. There is a chance that
noise (randomness) misleads us.
Statistical significance is important because it reflects your risk tolerance and confidence level. The metrics can
fluctuate from day to day, and statistical analysis provides the sound mathematical foundation for making
business decisions in a noisy environment.
PlayFab Experiments flags metric movements as statistically significant at 95% confidence or a p-value of 0.05.

Sample Ratio Mismatch (SRM)


A sample ratio mismatch (known as an SRM) is a data quality check that indicates a significant difference
between expected proportions of users among experiment variants (e.g. configured before the experiment
started) and the actual proportions of users observed at the end of the experiment.
An SRM indicates that there is some missing data or a redundancy issue that impacts the control and treatment
variants in an uneven manner. The basic principle of controlled experiments requires that the treatment and
control variants must be statistically equivalent. When this principle is violated, the results of the experiment can
suffer from a selection bias..
An analysis that has SRMs is generally viewed as untrustworthy and you should not use it to make decisions.
Indeed, if one's experiment has an SRM, do not draw any conclusions from the analysis (not until you have
addressed the SRM.)
How to detect SRM
Let's take an example where an experiment is configured to run with 10% traffic in each control and treatment
variants.

TYPE 1 DAY 2 DAY 3 DAY 5 DAY 7 DAY 14 DAY 21 DAY

Treatment 105 1,050 10,500 105,000 1,050,000 10,500,000 100,500,00


Variant 0
Count

Control 100 1,000 10,000 100,000 1,000,000 10,000,000 100,000,00


Variant 0
Count

Sample 1.05 1.05 1.05 1.05 1.05 1.05 1.05


Ratio

SRM p- 0.7269 0.2695 0.0005 ~=0 ~=0 ~=0 ~=0


value

In this scenario, even though the actual ratio between the two flights are the same in each scenario, one have an
increasingly smaller p-value for larger user counts in Treatment and Control. This indicates that the observed
outcome is not as expected.
How to investigate SRM
SRM investigation and resolution is a complex and uncertain process. Therefore, resolving an SRM requires a
structural approach, with a panoramic view, and an awareness of the likelihood of root causes and resolutions
strategies. For this,
Start with the question "why did this happen?"
Formulate a hypothesis on the cause of that SRM
Predict what would be the evidence observed if that hypothesis was true
Find those pieces of evidence
Analyze the cause to identify a solution
Asking follow-up questions can help in the investigation to devise the necessary steps for resolution. For
example:
Did this happen in only one analysis/experiment or in multiple?
What does the treatment do? What is the nature of the experiment?
Did something change between now (SRM) and before (previous experiment with no SRM)
Did any of the views, pipelines, filters change?
Common root-causes for SRMs
Treatment experience in the game crashes more than control experience
Treatment experience unintendedly sending different amounts of data. For example, an experiment on the
client that increases the telemetry buffer will certainly increase the amount of data that makes it back, which
will cause an SRM

Experiments as a Practice
Star t with a hypothesis
Hypothesize to ensure that the experiment has a clear goal and scenario for the experiment. Also, make
sure the changes you are testing are significant enough to matter.
To form a hypothesis, use the following template:
Because of observation [A] and feedback [B], the belief is that changing [C] for players [D] will make [E]
happen. It will be validated when I see [F] and obtain [G].
Schedule experiment correctly
To get reliable results, run your A/B experiments for comparable periods. Do account for seasonal peaks
and troughs.
Duration of an experiment
Give the experiment enough time. Insufficient time allocated for the experiment can skew the results. If
the run time is too short, you might not collect enough data points for a statistically accurate conclusion.
If the run time is too too long, you might risk missing out on conversions by not rolling the winning
variant to the potentials. If you are in doubt, it is perfectly reasonable to retest.
Pay attention to % of a flight
% of flight determines your sample size. Target the audience with the right sample size, otherwise, you
will not get reliable results and the decisions made based on that data may be flawed.
Avoid Type 1 and Type 2 errors Statistics in experiments provides probability, not a certainty.
Therefore, it cannot provide 100% certainty whether one variant of the experiment is best. So, avoid Type
1 and Type 2 errors.
To avoid type 1 error, raise the required significance level before reaching a decision (which we have done
for you by setting it to 95%, by default) and running the experiment longer to collect more data. And to
reduce the chance of type 2 error, increase the experiment's flighting population (sample size).
Do not make changes mid-way to an experiment
If you interrupt the test before the end of the ideal duration or introduce new variables that were not part
of the original hypothesis, the results will not be reliable. Meaning, it would be difficult to determine
whether one of the changes caused the lift in conversions or just a random chance.
Please note, the more variations there are, the longer you must run the tests to get reliable results. Take a
granular approach. The recommendation is to experiment with 2-4 variables in any variant group at the
same time. That gives the best balance of test duration and efficiency.
Pay attention to statistical significance as reflected in p-value
Make sure that the data is reliable. The measure of data reliability is the statistical significance which
determines that the results are not due to random chance.
p-values are used to determine statistical significance in a null hypothesis onto which AB experiments are
based. It measures the compatibility between the collected data and the null hypothesis. The lower it is,
the more confident one can be in rejecting the null hypothesis.
Keep an open mind
At times, you might be tempted to ignore statistical information in favor of using conventional
knowledge or even previous experience, to make the decision – no matter how much it surprises you. If
you are not convinced by the results of a test, run it again and compare the data.

Adopt Experiments Culture and Process


Experiments culture is valuable. You must imbibe it as part of the other processes, so everyone is benefitted
from it across the organization. Consistent A/B experimentation can substantially improve conversion as you
have a greater chance of finding ways to add positive product value for the players.
You can shift the decision-making paradigm from relying on HiPPOs (the Highest Paid Person’s Opinion) to
data-driven choices. More employee ideas will see daylight in the form of tests. Importantly, when it is easy to
try ideas, speak about results and the next steps. On top of it, employees feel motivated to come to work.
To build an experimentation culture, introduce reliable and repeatable processes for game iteration. You can
acquire a culture of constant experimentation by using the following foundational steps:
Set goals
Actionable experiment goals (ex. engagement) allow the team to move forward with experiments, rather
than getting stuck in abstract objectives like ‘growth’.
Test more with your team’s suppor t and prioritize
Collect and analyze qualitative and quantitative data such that hypotheses/ ideas can be brainstormed
and prioritized based on the business impact. Guide your team throughout the experimentation journey
using a reliable and repeatable framework, otherwise, the team will feel lost if you suddenly ask them to
experiment more and make multiple changes.
Communicate results back to your team
Build momentum around experimentation by communicating test results as a team. Sharing provides the
team with insights on how to iterate and improve future testing. Plus, gets people excited about further
experimentation.
Embrace failure
Failure is a part of testing, normalize failure. Do not let failure stall experimentation, reflect, learn, and
move on to continue experimenting.
Practice good experiment hygiene
Create a standard protocol for every experiment your team runs. It helps to keep experiments’ results
accurate and meaningful, regardless of who is controlling the experiment.

Recommended planning process for running experiments


STA GES DESC RIP T IO N

Oppor tunity Analysis

Investigation Experiment owner investigates and analyzes experiments


opportunities. Prioritize the experiments
STA GES DESC RIP T IO N

Experiment Design

Scoping Start experiment design. Identify goal metric(s) to formulate


a hypothesis

Feature Design Review Finalize design for feature/ experience change. As part of the
experiment, it is introduced to a treatment variant group via
variables

Coding Implement the feature change

Prod Deployment Review the experiment design. Deploy the associated code

Experiment Creation

Experiment Configuration Create an experiment in PlayFab

Experiment Execution

Run A/B Experiment Experiment starts as per the experiment configuration.


Experiences are orchestrated to the targeted audience.
Telemetry is collected and statistical computations are
performed

Experiment Analysis

Evaluate Results Evaluate the results via Scorecards

Make Launch Decision Stakeholders evaluate the launch decision

Roll-out or roll-back

Wrap-up Experiment Winning variant is rolled up to 100% of the audience


Experiments Key Terms
5/24/2022 • 3 minutes to read • Edit Online

To get comfortable with experiment as a practice and develop an understanding of the key-terms, read below:
Experiments
A/B experiments is a method of comparing two or more configurations of game experience (variants), whereas
multivariate experiments allows you to configure several game elements and determine which combinations
(variants) perform best at achieving your conversion goals.
This is done by splitting users randomly into two or more groups and providing different experiences to each
group over a period of time, and statistical analysis is done on the collected telemetry to determine which
variation performs better based on the goals you decide for the experiment
With PlayFab Experiments support both A/B testing (also known as split testing) and multivariate testing.
Conversion Rate
A conversion refers to any desired action that you want the player to take. Conversions do not have to be tied to
monetary goals. This can include anything from a click on a button to making a purchase and becoming a player.
Conversion is the goal of experiments. Conversions are an absolute number, whereas a conversion rate is the
number of conversions divided by the total player traffic.
Hypothesis
A hypothesis presents a claim about how a given intervention will affect player behavior. The hypothesis is a
combination of an idea about what scenarios to experiment and why, and what changes might appear after the
changes.
Segment
Segments organizes individual players into group(s) which shares common characteristic(s) as per the user-
defined qualifying condition(s)/criteria(s).
You can flight an experiment with a customized experience for a Segment to verify the hypothesis that an
audience will respond more positively.
% of target audience
A percentage of the total player base that are considered for the experiment and is associated with the control or
treatment variant.
Control Variant
A control variant is an existing experience that is used in an experiment as a measure of comparison to ensure
that the experiment works. It provides a baseline measurement for the experiment. It makes sure that the
treatment you are giving is causing the experimental results, and not something outside the experiment.
Treatment Variant
A treatment variant receives the experimental treatment(s) or difference in experience(s) in an experiment. It is
the treatment variant(s) that are studied in an A/B experiment and contains the experience changes.
Variables
Variables are defined to set the feature or experience configuration. Defining feature variables allows you to
iterate on your feature without redeploying the code.
P-value
The p-value in an A/B experiment is the probability that there is no difference between variant groups.
When the p-value is high it implies that any difference between the A and B groups is due to sampling noise.
When the p-value is low (below our threshold) it implies that the there is a real difference between variants and
the shown delta is the most likely actual difference.
Confidence Interval
In A/B testing, confidence intervals mitigate the risk of sampling errors, in a sense manages the risk associated
with implementing a new variant. If the tool indicates, “We are 95% confident that the conversion rate is X% +/-
Y%,” then you need to account for the +/- Y% as the margin of error. How confident you are in your results
depends largely on how large the margin of error is. If the two conversion ranges overlap, you need to keep
testing to get a valid result.
Type 1 Error : A type 1 error is a measure of “false positive,” an incorrect belief that a variation in an experiment
has made a statistically significant difference. A conclusive winner is declared although the test turned out as
inconclusive.
Type 2 Error : A type 2 error is a measure of “false negatives,” an incorrect belief that a variation in an
experiment has made no statistically significant difference. No conclusive winner is declared between a control
and a variation when there should be one.
Billing for PlayFab Experiments
5/24/2022 • 2 minutes to read • Edit Online

This document describes how Experiments are metered and billed. In PlayFab's free Development mode, titles
can use Experiments without a fee as long the aggregate number of player accounts is less than 100,000
(attempts to create additional player accounts will fail). For Live titles (on the pay-as-you-go model – Standard,
Premium, or Enterprise), Experiments is billed under the Insights credit system with no consumption limits.
Insights credits are a virtual currency that allows all Insights services to be billed through a common value.
Please note, Experiments service operation has no association with the performance characteristics control of
Insights service.
The billing summary page page provides a daily snapshot of your month-to-date estimate charges with
Experiments service’s Insights credit as breakdown. Admin or billing permissions are required to view the Billing
Summary page. The comprising factors which account for the accrued Insights credits based on the
consumption of the Experiments service are below.
What factors contribute to the consumption billing for Experiments service under Insights meter? The metering
starts only during the run of an experiment and stops when the experiment is completed or stopped. There are
three key factors used to bill additional Insights credit utilization for Experiments service.
1. Size of the target audience for treatment assignment. The participating audience of an experiment is either all
the active players or is determined based on the selected Segment’s computation in a real-time manner. Also,
the process of assignment and instrumentation of a treatment configuration is done by stamping variant IDs
onto the player profile. So, the larger the target audience, the more resources are consumed, which results in
higher Insights metering.
2. Computation of metrics. This is measured in analysis computation job minutes for each scorecard. This is
variable and the determining factors are the set of metrics (i.e., each metric’s definition and complexity) and
the number of relevant Entity events (with type ‘player’) associated with the involved metric set. So, the
larger the associated event set (PlayStream or Telemetry) for a metric set, the higher the Insights metering.
Please note, currently, we support a pre-defined metric set, so there are only two events—player_logged_in
and player_realmoney_purchase—for which the scorecard computation happens, and the events’ variable
size could add to the computation job minutes.
3. Experiment duration. The longer the duration of an experiment, the higher the consumption of the
Experiments service, which results in higher Insights metering.
Please note, the Experiment APIs and PlayStream events are accounted for outside of the Insights credit system.
The Experiment APIs along with the Overrides assignment usage are accrued under the profile read/ writes
meters. Also, the Experiments’ PlayStream events are accrued under the events meters.
Metrics
5/24/2022 • 2 minutes to read • Edit Online

What are metrics?


When raw data is combined to produce a meaningful measure, we refer to the result as a metric. Certain metrics
have become standard across the game industry, because they’ve proven valuable at informing the team and
guiding the decision-making process.
Some examples include:
New Players
Monthly Active Users
Session Length
Retention
How PlayFab supports metrics
PlayFab’s metrics offering automatically calculates these industry-standard metrics for you on a daily basis,
making them available to explore from the Reports and Trends tabs in the Analytics section. PlayFab offers views
that are easy to digest, filter, and analyze.
Which metrics are available?
You can explore the full set of metrics available in the Metrics and Terminology section.
Metrics and terminology
5/24/2022 • 3 minutes to read • Edit Online

Engagement metrics
M ET RIC DEF IN IT IO N

API Usage API Usage statistics are summarized by counts of total


calls, total successful calls, and total errors.

DAU Daily Active Users gives you the count of unique players
who logged in on a given day, from 12AM to 11PM UTC.

Installs The count of installations on new devices, measured by the


number of unique device IDs. This number may include both
new and returning players.

Logins The count of player login events. Unique logins count the
number of unique players. The total logins counts all login
events, which can be used to track number of sessions
played. Average logins per user tracks the average number
of login events per active player. Note: To obtain an accurate
distribution of session counts, we recommend logging in the
player on each session start - even if the old login ticket is
still valid.

MAU Monthly Active Users . In the Rolling Thirty Day Totals


Report, MAU refers to the count of unique players who
logged in during the span of last 30 days. In the Monthly
Totals Report, MAU is calculated per month, based on the
first and last days of a given month.

New Users The count of players who logged in for the first time, thus
creating new player profiles.

Retention The percentage of players who logged in again exactly N


days after a reference date, marked as day 0 . The Thirty Day
New User Retention Report considers new users who joined
the game within the span of last 30 days. The Thirty Day
Retention Report includes both new and returning users who
logged into the game within the span of last 30 days.

Revenue metrics
M ET RIC DEF IN IT IO N

ARPDAU Average Revenue Per Daily Active User in USD.

ARPPU Average Revenue Per Paying User within a specified


time period (e.g., hourly, daily, or monthly) in USD.
M ET RIC DEF IN IT IO N

ARPU Average Revenue Per active User within a specified time


period (e.g., hourly, daily, or monthly) in USD.

Average Purchase Price The average transaction amount in USD (=


Revenue/Purchases).

Conversion The percentage of players who become paying users. The


Thirty Day New User Conversion Report tracks purchases
made by new user cohorts over a 30 day period. Unlike
Retention Reports, the Conversion Report tracks a
cumulative total of players who converted within a given
time span.

Purchases The count of transactions.

Top Items The top 100 items which generated the most revenue in
your game within a specified report period.

Top Spenders The top 100 players who spent the most money in your
game within a specified report period.

Transaction Revenue The sum of Transaction amounts in USD. Transactions made


in other currencies are converted into USD, based on daily
exchange rates.

Unique Paying Users The count of unique players who spent money in your game.

Terminology
M ET RIC DEF IN IT IO N

Cohor t A group of players who joined or played the game on a


given day, marked as Day 0.

Event Events mark the transition between important states in your


game, such as a player logging in, making a purchase,
leveling up, or dying. A data event is a data structure that
captures information about the event. PlayFab uses JSON to
represent data events. Standard events are generated
automatically during use of PlayFab services; games can
generate custom events to track other important game-
specific events. All data events can be saved, aggregated,
reacted to, and analyzed via PlayFab’s real-time data pipeline,
known as PlayStream.

Platform PlayFab tracks four different types of platforms: OS (iOS,


Android), Device Type (iPhone, iPad, Samsung Android, PC,
Xbox, etc.), Account Type (Steam, Facebook, Kongregate,
Custom, etc.), and Payment Type (iTunes, Google Play, Steam,
Facebook, Xsolla, etc.).
M ET RIC DEF IN IT IO N

Segment A group of players who share similar properties, e.g.,


geography, demographics, platform, purchase patterns, etc.
In addition to standard segments, users can define custom
segments. Note that segment definitions are limited to
properties in the entity profile.

Timestamp (TS) All PlayFab real-time analytics and reports are based on
Coordinated Universal Time (UTC ).
Real-time analytics: core concepts
5/24/2022 • 2 minutes to read • Edit Online

The analytics system gives you precise insights into the activities going on inside of your game.
How many players did you have today?
Where do they struggle?
What do they like?
How many games were played?
How much XP was gained?
How many chests were opened - and on which levels?
What is the average time for completing a certain level?
Such information is invaluable to you for marketing, level design, UX troubleshooting, and other aspects of your
product development.
At its core, the analytics system provides you with the tools to aggregate, query, and analyze the events
generated by your game, build reports, and export and manipulate the raw data.

PlayFab event
An event - as a data structure - represents a change in state for your game. Events are represented as JSON
objects. Each event has four parts:
1. Name (or unique type identifier) - (What happened?)
2. Entity (player, title, or character) - (Who's guilty?)
3. Timestamp - (When did it happen?)
4. Associated Data ( a.k.a. Body ) - (What are the relevant details?)
It is important to distinguish between Automatic and Custom events. Our Generating PlayStream Events Tutorial
explains the difference.

Event flow
The core of any analytics system is the event flow - which is a all-inclusive list of events sorted by time.
Your players are going to produce a large number of different events. But these events are not captured by
themselves - you need an analytics system to capture them for later analysis.
A solid analytics system allows you to group, sort, filter, count, transform, and perform calculations on a given
set of events, turning the event flow into valuable, up-to-date information that you can use to run efficient
LiveOps.

Guides
Webhooks: Game Manager page for automatically triggering non-PlayFab servers on specific game events.
S3 Event Archiving: Game Manager page for accessing recent PlayStream events.
Metrics quickstart
5/24/2022 • 2 minutes to read • Edit Online

There are two primary ways to explore your metrics from PlayFab Game Manager:
1. Trends - A collection of graphs visualizing performance over time.
2. Repor ts - Data tables comparing. Covered in detail in the Reports Section.

Trends tab
The Trends tab offers an easy way to view and analyze performance across eight key performance indicators:
1. MAU
2. DAU
3. New Players
4. Screen Time
5. Screen Frequency
6. Classic Retention
7. Revenue
8. Stickiness
The Trends tab is updated once daily at the close of the UTC day. For details on each metric, see Metrics and
terminology.
The Trends tab consists of three sections:
1. Filters
2. Spark Cards
3. Graphs

Filters
At the top, there are three page-level filters that can be applied. Choosing any filter will update all Spark Cards
and Graphs to match the current active selection:
Time: Choose the time interval to explore, from seven days to six months.
Platform: See only data for individual device types such as Android, iPhone, or Windows.
Region: See only data from a specific geographic region.

NOTE
Platform and Region filters are not currently supported for Revenue. This will be resolved in a future release.
Spark Cards
The Spark Cards are designed to offer an at-a-glance view of what happened that particular day. Each Spark
Card consists of:
A trend line
The actual value from the most recent UTC day
The trend comparing the most recent value against the period start.
Definitions for each are obtained by hovering over the metric or by tapping, if using a mobile phone.

Graphs
The Graphs provide trend data for each of the six metrics, through that day. In some cases, the drop-down over
each graph can be used to toggle the active metric. For example, the Active Players graph can show either DAU
or the Rolling 30-Day MAU.
In the upper right-hand corner of each graph, individual lines can be toggled on and off. Doing so dynamically
re-scales the y-axis. Additionally, in the Retention Graph, D1 and D7 can be disabled to emphasize variations in
D14 and D30.
Hover over any data point to display the actual value for the selected day. To the right of each graph, supporting
metrics offer additional insights such as the average and/or total for the period.

Data Collection
If your title is not collecting device information or sessions events, some components of the Trend Explorer will
be unavailable. To enable these, change your settings in the Data Collection tab. SeeData Collectionfor more
details.
Metrics Tutorials
5/24/2022 • 2 minutes to read • Edit Online

These tutorials teach you how to use metrics.


Generating PlayStream events
Metrics and Terminology
Real-Time Analytics - Core Concepts
S3 Event Archiving
Sessions
Generating PlayStream events
5/24/2022 • 2 minutes to read • Edit Online

This tutorial provides an overview of automatic and custom PlayStream events in PlayFab.

Automatic event overview


As the name implies, an automatic event is one that occurs automatically with a normal API method call. Most
existing API methods will generate PlayStream events.
Sometimes, however, you will need to capture events that are very specific for your game, and are not provided
by PlayFab out of the box.
For that purpose, consider using a custom event (as described in the next section, Custom Event Overview).
Example
If an email and password pair is valid, the following API call will sign in a player with email and password.

PlayFabClientAPI.LoginWithEmailAddress(new LoginWithEmailAddressRequest() {
Email = "my@email.com",
Password = "qwerty"
},
result=> Debug.Log(result.PlayFabId),
error=> Debug.LogError(error.GenerateErrorReport()));

As a side effect, PlayFab will record a player_logged_in event.

Custom event overview


While PlayFab records a lot of events automatically, sometimes you need events that are very specific for your
game.
The concept of custom events allows you to post events with an arbitrary type and name.
Similar to automatic events, custom events are fully reflected through real-time analytics tools. Unlike automatic
events, you need a little bit of custom code to post custom events.
Custom events can be classified by entity. A custom event can be bound to a player, character, or title. An event
entity reference is specified using these two fields:
1. EntityType
2. EntityID
Relevant API Calls
WritePlayerEvent
WriteCharacterEvent
WriteTitleEvent
Example: Post your own custom event
You want to aggregate information about players opening various chests. Along with standard event
information, you want to record ChestType and LevelID .
Unfortunately, PlayFab does not provide a corresponding Automatic Event out of the box. Use a custom player
event to solve the problem.
Prerequisites
Your player is already logged in. In your code, you have a callback OnChestOpen , LevelID , and ChestType are
passed into that callback.
Solution
Once executed, the following code will post your custom player event.

private void OnChestOpened(string chestType, int levelId) {


PlayFabClientAPI.WritePlayerEvent(new WriteClientPlayerEventRequest() {
Body = new Dictionary<string, object>() {
{ "ChestType", chestType },
{ "LevelId", levelId }
},
EventName = "player_chest_opened"
},
result => Debug.Log("Success"),
error => Debug.LogError(error.GenerateErrorReport()));
}

1. The method receives ChestType and LevelId .


2. Use the WritePlayerEvent API call for posting a custom event bound to a player.
3. Provide a body, specific for your events and your needs. In this case we provide the ChestType and LevelId
fields.
4. Provide an event name identifying your custom event. In this case we use the player_chest_opened event
type name.
Set up an Amazon S3 bucket for PlayFab event
archiving
5/24/2022 • 2 minutes to read • Edit Online

This topic describes how to set up an Amazon S3 bucket so that you can archive your PlayFab events to it.

Setting up Amazon S3 bucket


Once you have created an Amazon account:
1. Navigate to Ser vices .
2. Select S3 .

The S3 page contains an overview of all your buckets.


Select the Create bucket button to create a new bucket.
To create your new S3 bucket, you must go though a 4-step wizard:
1. Assign a unique, DNS-compliant Bucket name for your bucket. Remember this name, you will need it when
configuring your PlayFab event archiving.
2. When you are done, select the Next button.
You will be offered the option of adding Versioning , Logging , and Tags for your Bucket .
1. Select the Next button when you are done.
1. During the step shown below, make sure that you have checked the Read/Write boxes for access to objects.
2. Select the Next button when you are done, as shown below.
1. In this last step, double-check your settings, and select the Create bucket button, as shown below.
Configuring Amazon access
In order to archive events, you will need to give PlayFab access to the bucket on your behalf. This is done by
means of an Access Key.
1. Double-check that you have your newly created bucket in the list of S3 services.
2. Select your account Name in the top right corner.
3. Then select My Security Credentials , as shown in the drop-down menu below.
Locate the Access Key list.
Select the Create New Access Key button.

1. Expand the Access Key data.


2. Save the Access Key ID .
3. Save the Secret Access Key . You will need both keys when configuring your PlayFab Event archiving.
4. Select the Close button.
Sessions
5/24/2022 • 2 minutes to read • Edit Online

PlayFab supports logging events to calculate focus time and session duration. You can learn even more on our
blog.

Supported SDK versions


Session support is currently only available in Unity SDK. Support for our other SDKs will be added in the future.
You'll need to have the 180829 version or newer. This SDK first introduces two new events that can be
configured to be emitted from the client automatically:
1. client_session_start
2. client_focus_change

Logging and managing events


To begin collecting these two events, you'll first need to integrate the Unity SDK in your client.
Instructions on how to do this can be found in the Unity3D quickstart.
Presently, these events are disabled by default, though we plan to change this in the future. You can manage the
collection of focus time from Game Manager:
Navigate to Settings .
Go to Data Collection .
In the Options section, toggle this option ON or OFF .

NOTE
Disabling this option will prevent these events from being emitted by the client.
You can also disable these from the code, by setting the option shown below to true in your title setup, as
shown below.

PlayFabSettings.DisableFocusTimeCollection = true

Legacy Instructions
If your game uses an SDK between the 180716 and 180809 , it's possible for you to send the focus time events,
although it requires additional steps.
Because these events leverage the WriteEvents API, you'll first need to ensure the Enable Entity API flag is
enabled (checked) in the SDK settings at the time you update the SDK.
Next, you'll need to log into the entity system, by adding the line shown below to each of your login requests.

LoginTitlePlayerAccountEntity

Once you've done that, you should see these same events.
Reports
5/24/2022 • 2 minutes to read • Edit Online

We know the hard work doesn’t end at launch – that’s just the beginning. To maximize a game’s potential to
connect with players, to keep them engaged, and earn revenue, you need to a reporting solution to monitor
your progress.
PlayFab Reports are designed for easy access to the critical metrics of your game at a glance. This set of pre-
generated reports is available in the Analytics section of Game Manager.
From there, you can dive into daily, monthly, and 30-day rolling views that focus on engagement and
monetization. Each report can be downloaded as a CSV for use in custom applications. In addition, you can opt
to receive daily summary e-mails delivered to your inbox.
Reports quickstart
5/24/2022 • 2 minutes to read • Edit Online

The Repor ts page gives you access to various reports composed from events, and broken down by dates.

IMPORTANT
Before using Repor ts , make sure you have executed some API calls which have been captured by the Repor ts system
already.

Access reports
To access the Repor ts page:
1. Use the side bar menu and navigate to Analytics .
2. Select the Repor ts tab.

Reports overview
The example shown below shows an overview of the Repor ts page.
1. The first section allows you to filter Repor ts by Type (Name ).
2. The Date column lists the time intervals for all Repor ts that have been generated. You can select the
Date label to access report details for a specific date.
3. The Name column identifies the Repor t Type uniquely. You can select the Name label to access report
details for the corresponding Date .
4. When Repor t data is available, you can download a CSV representation of the data by selecting
Download CSV .
5. When Repor t data is not available for a given day (no events that day), the Date and Name labels will
render black, will not be selectable, and the option of downloading the report as a CSV will not be
available.
Report Types
Daily, Monthly, and Rolling Thirty-Day Overview and Totals Reports
Tracks hourly, daily, and monthly logins, revenue, and API usage.
Thirty-day Retention Report
Tracks the percentages of all active players who return to your game over 30 days.
Thirty-day New User Retention Report
Tracks the percentages of new players who return to your game over the first 30 days.
Thirty-day New User Conversion Report
Tracks the percentages of new players who spend money within the first 30 days.
Daily and Monthly Top Spender Report
Tracks the top 100 spenders in your game.
Daily and Monthly Top Items Report
Tracks the top 100 items in your game.
Daily AB Test KPI Report
Evaluates the effectiveness of your A/B test experiments.
Daily API Usage Details Report
Tracks the PlayFab API calls used by your title.
Daily and Monthly CDN Usage Report
Tracks Content Deliver y Network (CDN ) usage by your players.
Daily Abuse Reports History Report
View and read player bug reporting, and/or let players report each other for cheating.

NOTE
The Name column is never selectable on this report, but the Download CSV column will still work if there is data
present.
Reports Tutorials
5/24/2022 • 2 minutes to read • Edit Online

The Reports tutorials show you how to create and run reports.
Daily A/B Test KPI Report
Daily Abuse Reports History Report
Daily and Monthly CDN Usage Report
Daily and Monthly Top Items Report
Daily and Monthly Top Spender Report
Daily and Monthly Top Details Report
Daily and Monthly Rolling 30-Day Overview and Totals Reports
Thirty-day New User Conversion Report
Thirty-day New User Retention Report
Thirty-day Retention Report
Daily A/B test KPI report
5/24/2022 • 2 minutes to read • Edit Online

Overview
The Daily A/B test Key Performance Indicators (KPI) report shows the outcome of an A/B test, broken down by A
and B buckets.

The Key Performance Indicators for A/B tests include:


DAU (Daily Active Users)
Average Logins Per User
ARPDAU (Average Revenue per Daily Active User)
Total number of Transactions
Total number of Unique Payers
Average Transactions per Payer
Retention for Day 1, 3, 7, 14 and 30

Populating the report


The first step in setting up A/B testing is to create an A/B test using the PlayFab Game Manager. To do this:
1. Select Automation from the menu to the left.
2. Go to the A/B Testing tab.
3. Create a New A/B Test and configure the A/B test name and user Buckets .

NOTE
You can have up to 5 Buckets with independent ratios (%).
Please refer to the Customer Stores for Player Segments tutorial for further information on A/B testing with
stores that are available only to players from defined player segments.
Daily Abuse Reports History Report
5/24/2022 • 2 minutes to read • Edit Online

Overview
The Daily Abuse Reports history report contains a CSV document with all of the player reports that happened
during the specified day.
In the example shown below, a player with ID of 6079A16A9E4FB67 is reporting a player with ID of
94A248B3B9E628F2 for the reason Test Repor t on 5/14/2017.

NOTE
For GDPR compliance reasons, the Daily Abuse History Reports are only available for the past 30 days. To learn more, visit
our GDPR documentation.

Using this information, you can then use the reportee ID, to quickly look up the reported player and investigate.

Populating the report


The following API call will produce new entries for this report.
public void ReportPlayer() {
PlayFabClientAPI.ReportPlayer( new ReportPlayerClientRequest() {
ReporteeId = "94A248B3B9E628F2",
Comment = "I think this person is cheating! Please, check!"
}, result => {
// Success
}, error => Debug.LogError(error.GenerateErrorReport()));
}
Daily and Monthly CDN Usage report
5/24/2022 • 2 minutes to read • Edit Online

Daily Content Usage report


The CDN Usage report contains two graphs displaying content usage over a 24 hour period:
1. The Data Volume graph illustrates the distribution of transferred bytes.
2. The Access Count graph shows the distribution of content downloads over a specified period of time.

Monthly Content Usage Summary report


This report summarizes monthly content usage. The table within it contains the amount of content bytes
transferred, as well as the total number of downloads during a specified month.

Populating Content Usage reports


The code in the template shown below may be used to introduce some data for the reports.
public void GetContent()
{
PlayFabClientAPI.GetContentDownloadUrl(new GetContentDownloadUrlRequest() {
HttpMethod = "GET",
Key = "ContentKey"
}, result => {
// Implement your own Download function based on URL
DownloadContent(result.URL);
}, error => {
Debug.LogError(error.GenerateErrorReport());

});
}

It is important to understand that the GetContentDownloadUrl API call, on its own, does not produce a new
entry in the report.
Instead, it provides you with a URI for the content download. You may use any HTTP request technique to
execute a GET request. Once this is done, a new entry will be added and reflected in both reports.

How to work with report charts


PlayFab report charts all follow the same model:
1. In the top area of the page, you usually get a Control Panel . This contains a report name, observed time
period, and Prev/Next buttons to switch between the time periods.
2. The Char t Panel area shows the available data as a chart, where the horizontal axis corresponds to the
time flow, and the vertical axis corresponds to the number of relevant instances - such as API calls,
purchases, users, and so on, depending on the report type.

3. The metrics available in the Timeline area contain the sum of all the instance across the time period (SUM ),
the average number of instances through all the timestamps (AVG ), the peak value (MAX ), and the lowest
value (MIN ).
Daily and Monthly Top Items report
5/24/2022 • 2 minutes to read • Edit Online

Overview
The Daily and Monthly Top Items report contains a list of top selling items, or bundles, in a given day or month.
This list includes:
Item names from your primary catalog
Associated numbers of sales
Total revenue
The report can assist you in identifying trending items over time, which can be useful for planning future
promotions or events.
The Daily and Monthly Top Items report contains a list of top selling items or bundles in a given day or month.
Both daily and monthly tables within these reports include item names from your primary catalog, associated
number of sales, and total revenue.
You can utilize the data contained within this report to identify trending items on visible timelines - a feature
that is useful for the design and execution of promotions and events.

Populating the reports


Please refer to our tutorials for Catalogs, Stores and Sales, and Non-receipt Payment Processing to learn about
setting up in-game stores and conducting payments.
Daily and Monthly Top Spender report
5/24/2022 • 2 minutes to read • Edit Online

Overview
The Daily and Monthly Top Spender report shows the list of players who spent money in your game on a given
day or month, sorted by the transaction amount.

NOTE
For GDPR compliance reasons, the Daily Abuse History Reports are only available for the past 30 days. To learn more, visit
our GDPR documentation.

You can select the PlayFab ID label to quickly navigate to the Player's Details page.

The Daily and Monthly Top Spender report shows the list of players who spent money in your game on a given
day or month, sorted by the transaction amount.
You can select the PlayFab ID label to quickly navigate to the Player's Details page.
Populating the Reports
Please refer to Non-receipt Payment Processing tutorial to learn how to conduct payments.
Daily API Usage Details report
5/24/2022 • 2 minutes to read • Edit Online

Overview
The daily API Usage Details report contains statistics for each API call, aggregated by the API name on an hourly
basis. The table contains the following metrics:
Total API Calls , Total Errors and Total Successful - These columns allow you to check the overall usage
and stability of your API calls.
Average Response Time , Total Response Time , Average Received bytes , Total Received bytes ,
Average Sent bytes , and Total Sent (MB ) - These columns are useful for monitoring system performance,
as well as optimizing some user-defined, heavy-duty function calls (for example, CloudScript).

If you experience lag spikes in your application while executing API calls, you can refer to this report to track
down the underlying cause.
For example - using the report, you will be able to check whether the data was too large, or that a handler
worked inefficiently. You can further utilize the report to tune the performance of CloudScript execution by
adjusting its behavior and associated data.

Populating the report


Any API call will be captured and included into this report. Check the PlayFab API Reference documentation for
the list of all API options.
Daily, Monthly, and Rolling Thirty Day Overview
and Totals reports
5/24/2022 • 2 minutes to read • Edit Online

Introduction
PlayFab offers a set of daily and monthly Key Performance Indicator (KPI) reports, including:
Total Logins
Unique Logins : Daily reports (DAU ) or Monthly and Rolling Thirty Day Reports (MAU )
New Users
Unique Paying Users
Transaction Revenue
Purchases
Total API Calls
Total Successful API Calls
Total API Call Errors
Average Revenue Per User (ARPU )
Average Revenue Per Paying User (ARPPU )
Average Purchase Price
An Overview report contains trend charts of each metric during the past 24 hours (daily), past 30 days (rolling
30-day), and in last month (monthly).
A Totals report contains the summary of each metric shown in the overview report. Daily and Rolling Thirty Day
reports are generated on a daily basis, whereas Monthly reports are generated on the first day of each month.
Report times are based on Coordinated Universal Time (UTC). For additional details on metrics, see Metrics and
Terminology.

Totals reports
Totals reports include a table, which contains the 12 Key Performance metrics described in the introduction.

Overview reports
Overview reports consist of 12 trend charts - one for each metric described in the introduction. Working with
charts is described later in this tutorial.
Populating the reports
Any API call may introduce new data for total API calls, total successful API calls, and total API call errors.
Once executed, an API call will be added to total API calls.
If there is an error that is introduced, it will be recorded to total API call errors.
If no error is introduced, it will belong to total successful API calls.
Please consult our PlayFab API Reference documentation to review all available API calls.
The following API calls will introduce new data for total logins and total unique logins:
LoginWithAndroidDeviceID
LoginWithCustomID
LoginWithEmailAddress
LoginWithFacebook
LoginWithGameCenter
LoginWithGoogleAccount
LoginWithIOSDeviceID
LoginWithKongregate
LoginWithPlayFab
LoginWithSteam
LoginWithTwitch
LoginWithWindowsHello
The API calls shown below will introduce new data for total new users.
RegisterPlayFabUser
RegisterWithWindowsHello
The API calls shown below will introduce new data for total new users if the CreateAccount flag is set.
LoginWithAndroidDeviceID
LoginWithCustomID
LoginWithFacebook
LoginWithGameCenter
LoginWithGoogleAccount
LoginWithIOSDeviceID
LoginWithKongregate
LoginWithSteam
LoginWithTwitch
The unique paying users, revenue, purchases, Average Revenue Per User (ARPU), Average Revenue Per Paying
User (ARPPU) and average purchase price metrics are used to analyze purchases and payments.
See the Non-receipt Payment Processing tutorial, for more information on conducting payments.

How to work with report charts


PlayFab report charts all follow the same model:
In the top space of the page, view the report name, time period, and Prev/Next buttons to switch between the
time periods.
Move your cursor along the timeline in the chart to view the associated interactive data.

Metrics available in the chart timeline include:


The average number of instances through all the timestamps (AVG).
The peak value (MAX).
The lowest value (MIN).
Thirty Day New User Conversion report
5/24/2022 • 2 minutes to read • Edit Online

Overview
The Thirty Day New User Conversion report illustrates the percentage of players in a given Cohort who spent
money in the game during their first 30 days.
A Cohort of players is formed every day by grouping newly-registered players. Cohort size is indicated by the
number of players in a cohort.

NOTE
Unlike Retention reports, the Conversion report tracks a cumulative total of players who converted within a given time
span.

The example report shown below was generated on 2/13/2018 . On 1/14/2018 under the Cohor t column,
77,532 new players created accounts in the example title.

Under the Day 0 column of that date, 0.50% of these players made at least one transaction in the game.
Since conversion reflects a cumulative total of players, these percentage values increase along the time span,
and reach 1.07% on the 30th Day - which corresponds to the report generation date, 2/13/2018 .
For additional details, see Metrics and Terminology.

Populating the report


To populate this report, you must register a new user, log in, and then conduct purchases several days in a row.
This, however, will produce trivial results, (with user conversion at 100% for each day). Throwing in several
users and skipping some days will produce more interesting results.
The following API calls may be used to create new user accounts:
RegisterPlayFabUser
RegisterWithWindowsHello
The following API calls will also create a new user account and log you in automatically, if the CreateAccount
flag is present:
LoginWithAndroidDeviceID
LoginWithCustomID
LoginWithFacebook
LoginWithGameCenter
LoginWithGoogleAccount
LoginWithIOSDeviceID
LoginWithKongregate
LoginWithSteam
LoginWithTwitch
Finally, you may use following API calls to log in:
LoginWithAndroidDeviceID
LoginWithCustomID
LoginWithEmailAddress
LoginWithFacebook
LoginWithGameCenter
LoginWithGoogleAccount
LoginWithIOSDeviceID
LoginWithKongregate
LoginWithPlayFab
LoginWithSteam
LoginWithTwitch
LoginWithWindowsHello
Thirty Day New User Retention report
5/24/2022 • 2 minutes to read • Edit Online

Overview
The Thirty Day New User Retention report tracks the percentage of new user cohorts who return to the game on
subsequent days.
A Cohort of players is defined by grouping newly registered players on a given day (Day 0 ) and their retention
is tracked over a 30-day period.
Cohort size is determined by the number of players within it.
The example report shown below, was generated on 2/5/2018 . On 1/6/2018 , 39,132 new players created
accounts in the example title.

Since Day 0 is an initiation date for a new Cohort, this column always has 100% retention rate.
Then 33.84% of those players logged in again the next day, 24.64% in two days later, and so on. 10.84% of the
Cohort returned on the 30th day, which corresponds to 2/5/2018 .
For additional details, see Metrics and Terminology.

Populating the report


To populate this report, you must register a player and then have them log in for several days in a row at least
once.
This, however, will produce trivial results, (with 100% retention for each day).
Throwing more players into the process and skipping some days will produce more interesting results.
The following API calls may be used to log in:
LoginWithAndroidDeviceID
LoginWithCustomID
LoginWithEmailAddress
LoginWithFacebook
LoginWithGameCenter
LoginWithGoogleAccount
LoginWithIOSDeviceID
LoginWithKongregate
LoginWithPlayFab
LoginWithSteam
LoginWithTwitch
LoginWithWindowsHello
To register a player you may use the following API calls:
RegisterPlayFabUser
RegisterWithWindowsHello
You may also you use the following API calls to register and log in simultaneously if the CreateAccount flag is
set:
LoginWithAndroidDeviceID
LoginWithCustomID
LoginWithFacebook
LoginWithGameCenter
LoginWithGoogleAccount
LoginWithIOSDeviceID
LoginWithKongregate
LoginWithSteam
LoginWithTwitch
Thirty Day Retention report
5/24/2022 • 2 minutes to read • Edit Online

Overview
The Thirty day Retention report table illustrates how many of your players came back to the game within a 30-
day period.
A new Cohort of players is formed every day, based on all the players (new and returning), who have logged in
to your game on a given day (Day 0 ).
Cohort size is determined by the number of players within it. Then each cell shows the percentage of players
(%) from a given Cohort who returned on each subsequent day.
The Thirty Day Retention report table illustrates how many of your players came back to the game within a 30-
day period.
The example report shown below was generated on 1/24/2018 . It shows, for instance, that on 12/25/2017 ,
1.38M users logged in.

Then 61.85% of them logged in the next day, and 55.85% of them logged in two days later.
Finally, 18.6% came back 30 days later, which corresponds to the report generate date, 1/24/2018 .
This report, in addition to the New User Retention Report, is especially useful when you are running a LiveOps
event, and want to check its effect on boosting engagement of existing players. For additional details, see
Metrics and Terminology.

Populating the report


To populate this report, you need to register a player, and then have them log in several days in a row at least
once.
This, however, will produce trivial results, (with 100% retention for each day). Throwing more players into the
process and skipping some days will produce more interesting results.
The following API calls may be used to log in:
LoginWithAndroidDeviceID
LoginWithCustomID
LoginWithEmailAddress
LoginWithFacebook
LoginWithGameCenter
LoginWithGoogleAccount
LoginWithIOSDeviceID
LoginWithKongregate
LoginWithPlayFab
LoginWithSteam
LoginWithTwitch
LoginWithWindowsHello
Segmentation
5/24/2022 • 2 minutes to read • Edit Online

Segmentation lets you create targeted groups of players based on their player properties. When PlayStream
events are processed, your configuration will drive the addition of players into and out of the segments you
define.
This all happens in real time - so there should be no perceptual lag, even at large scale. If you can tie an event to
the thing you want to use as a differentiating factor, you can make a segment for it, and that segment will apply
retroactively to all players, based on the data in their profiles.
Let's say that you want to define a segment of players where XP > 3,000, then every player with XP > 3,000 will
now be in that segment.
In the example shown below, this particular segment will be evaluated anytime the statistic called
Total_XPGained changes. If the condition (> 3000) evaluates to true , then the player will enter the High XP
Players segment, and the corresponding action(s) will be triggered.

In this case, it will send a push notification, and grant gold to the player.
NOTE
You can also trigger a different custom action(s) when the player leaves a segment, allowing you to make any other
changes needed as a result.

There are a variety of basic actions available, including granting an item to the player, granting virtual currency,
changing a statistic, banning a player, sending a player an email or sending a Push notification. You can also
trigger custom CloudScript to be run instead.
Player segmentation quickstart
5/24/2022 • 2 minutes to read • Edit Online

Player segmentation is defined in Game Manager. Segments allow you to define useful or interesting groups of
players, and perform exclusive actions on that group.

Requirements
Players with and without a distinctive characteristic defined in PlayFab.
A defined CloudScript PlayStream Hook.
Example case: Run a custom CloudScript for every player who reaches an in-game goal
The defining characteristic of a player might be:
Login time
Linked device type
Tags
Real-world location
Statistic values
Virtual currency values
Real money purchases, and more.
For this example, our distinctive characteristic will be a statistic - specifically, players who achieve 50 str .

NOTE
Statistics are one of many possible options, and only specifically required for this example. Feel free to replace the statistic
requirement with another filter of your choice.

Our action will be to run a CloudScript function. CloudScript is by far the most flexible trigger option, granting
you the full control of player and segmentation information at the time of segment transition.
From the Game Manager screen:
Navigate to your Title .
Select Players from the menu on the left.
Move to the Segments tab.
Select New Segment .
The screen shown below is an example of the Segment described above.
The most complex part of this example is the CloudScript. Utilize the second parameter, Context, in your
CloudScript handler to identify the player, and segment transition.
Afterwards, perform any action you wish on the player, such as granting inventory items, virtual currency, player
data, or statistics.
See also: Best Practices for store segmentation
Segmentation Tutorials
5/24/2022 • 2 minutes to read • Edit Online

Segment Configuration
This tutorial show you how to set up player Segments.
Export Player in a Segment
This tutorial show you how to set export players in a Segments using ExportPlayersInSegment and
GetSegmentExport APIs. These APIs are a newer and better version of GetPlayersInSegment API.
Segment configuration
5/24/2022 • 7 minutes to read • Edit Online

The Segment configuration page, accessed from the Players tab in Game Manager , allows you to configure
a new or existing segment by adjusting the name, defining filters, and assigning tasks.
Each segment allows you to define useful or interesting groups of players, and perform exclusive actions on that
group.

How to create and access a segment


To access segment configuration:
1. Select Players from the menu on the left.
2. Select the Segments tab.
You may then choose to:
3. Use the New Segment button to create and configure a new Segment .
4. Locate an existing Segment , and select the name label to configure the Segment .

How to configure a segment


Prerequisites :
To configure a segment like the example in this tutorial, you will need:
Players with and without a distinctive characteristic defined in PlayFab.
A defined CloudScript PlayStream Hook.
In this example we are going to:
Configure a segment using this defining characteristic: all players that come from Canada.
Run a CloudScript function helloWorld for each player that enters the segment.
The defining characteristic of a player can be:
Login time
Linked device type
Tags
Real-world location
Statistic values
Virtual currency values
Real money purchases, and more.
Player's location is one of many possible options, and only specifically required for this example. Feel free to
replace the country/region requirement with another filter of your choice.
When a segment is defined, you have a variety of action options to run when a player enters or leaves the
segment.
CloudScript is by far the most flexible action, granting you full control of the player and segmentation
information at the time of segment transition.
Utilize the second parameter, Context in your CloudScript handler to identify the player, and segment transition.
Afterwards, perform any action you wish on the player, such as granting inventory items, virtual currency, player
data, or statistics.
In this particular case, segment configuration requires 4 simple steps:
1. Assign an appropriate name for the segment. It's a good idea to use a name that incorporates your Defining
Characteristic - Canada Players .
2. Assign conditions that a player has to meet to enter the segment. In this case we want a Location
(country/region) filter with the strict value: Canada.
3. Add a CloudScript action for the entered segment trigger. Configure the action to run the function you want.
In this example, we want helloWorld .
4. Commit by selecting the Save Segment button.
When a segment is defined, you have a variety of action options to run when a player enters or leaves the
segment. CloudScript is by far the most flexible action, granting you full control of the player and segmentation
information at the time of segment transition.
Utilize the second parameter, Context in your CloudScript handler to identify the player, and segment transition.
Afterwards, perform any action you wish on the player, such as granting inventory items, virtual currency, player
data, or statistics.
In this particular case, segment configuration requires 4 simple steps:
1. Assign an appropriate name for the segment (it's a good idea to use a name that incorporates your defining
characteristic - Canada Players ).
2. Assign conditions that a player has to meet to enter the segment. In this case we want a Location
(country/region) filter with the strict value: Canada.
3. Add a CloudScript action for the entered segment trigger. Configure the action to run the function you
want. In this example, we want: helloWorld .
4. Commit by selecting the Save Segment button.
Group (2) is a set of players that meet all defined conditions called Filters (3) .
In other words, to be part of a segment, a player must be part of at least 1 group. To be part of a group, a player
must meet all conditions (filters).
This is denoted by the OR/AND operators: filters are combined using the AND operator, while groups are
combined using the OR operator.
The screenshot shown below offers an example of how a segment can be defined. This segment consists of 2
groups. The first group is defined by 2 filters:
A player must be from Canada.
A player must have Apple Push notifications enabled .
The second group is also for players from Canada, but they must have Google Push notifications enabled .
In the end, we have a segment of players from Canada with either Google or Apple push notifications.
Each filter has a unique configuration and purpose. As of 4/30/2017, the following filters are available:
The All players filter - This filter has no configuration and is unique, because it allows you to create a
segment of all players. This comes in handy when you want to run automatic operations for every new
player (segment actions are described in the How to manage actions section, later in this tutorial).
The First login (date) filter - Allows you to filter based on first login datetime. For example, players that
have first logged in after 1/1/2017.
The First login (timespan) filter - Allows you to filter based on first login timespan relative to the current
datetime. For example, player that have first signed in 20 minutes ago (from now).
The Last login (date) filter - Allows you to filter based on last login datetime. For example, players that
have not signed since 1/1/2017.
The Last login (timespan) filter - Allows you to filter based on last login timespan relative to the current
datetime. For example, players that have not signed in for a week (from now).
The Linked user account to filter - Allows you to filter based on users linked accounts. For example,
players that have a Steam account linked with an email account.
The Location (countr y/region) filter - Allows you to filter based on player's country/region. For example,
players from Canada.
The Push notifications enabled with filter - Allows you to filter based on player push settings and
capabilities. For example, players that have Google push notifications enabled.
The Statistics value filter - Allows you to filter based on your own custom statistic attribute. For example,
players that inflicted 20000 damage in total.
The Tag filter - Allows you to filter based on whether a player has or doesn't have a certain tag. For example,
players that have a cheater tag.
The Total value to date in US filter - Allows you to filter based on how much USD currency a player has
spent in your game. For example, players that have spent over $30.
The Value to date filter - Allows you to filter based on how much of a certain currency a player has spent
in your game. For example, players that have spent 50 RUB.
The User origination filter - Allows you to filter based on the first authentication method that a player
used to start playing the game.

NOTE
The trick here is that a player may start with authentication based on, say, an iOS device ID, but later, the same player
may have a GameCenter account linked. In this case, user origination will be the iOS device ID. For example, players that
first signed in using an iOS device ID.
The Vir tual currency balance filter - Allows you to filter based on the custom virtual currency deposit of
a player. For example, players that have less than 50 Crystal.

How to manage actions


Each action needs a trigger in order to run. Some actions are run manually, triggered right from the page.
Sometimes, though, you have to select a trigger - an event that causes an action to run.
A trigger defines the context of the action. For example, a player entered segment trigger passes you the context
containing a reference to the player. The general workflow for the Actions panel is:
1. Select an Event condition , also known as a Trigger.
2. Select an action Type . PlayFab offers a variety of actions. If, at any point, you need more a flexible action,
consider a CloudScript action. This action type allows you to run your own CloudScript function.
3. Configure the action (specific for each action Type ).
4. Select REMOVE to remove the action from the trigger.
5. Select Add Action to add action to the trigger.

How to inspect player segments


It is possible to look up what segments a player belongs to by means of the Player Segments page. To access
the Player Segments page:
1. Select Players in the sidebar menu.
2. Then select the Players tab.
3. Locate the player you want to inspect, and select the ID label.
4. Finally, select Segments in the Players Toolbar .
On the Player Segments page, note the following:
1. The Player ID label identifies the player you currently inspecting.
2. The Segments table contains a list of all segments a player belongs to. Select the Segment name label to
configure a segment.
Export Players of a Segment
5/24/2022 • 2 minutes to read • Edit Online

This tutorial walks you through the steps needed to export the Player Profiles in a Segment using the
ExportPlayersInSegment API and GetSegmentExport API. These APIs are a newer and better version of
GetPlayersInSegment API.
Step 1
Send a POST request with the Segment Id as the payload to the ExportPlayersInSegment API. The ‘ExportId‘ in
the response is the unique identifier of the export operation.

NOTE
The API requires the ‘X-SecretKey’ header with the value being a Title Secret key. The ‘Content-Type’ header should be set
to ‘application/json’

Step 2
Send a POST request to GetSegmentExport API with the ExportId received in the above API call as the payload.
The response has the ‘State’ of the export operation. If the export has a status of ‘Complete,’ then the response
contains the ‘IndexUrl’ from which the Index file can be downloaded.
NOTE
The API requires the ‘X-SecretKey’ header with the value being a Title Secret key. The ‘Content-Type’ header should be set
to ‘application/json’

Step 3
Download the Index file from the IndexUrl. The Index file is a file in which each line is a URL from which a
fragment of the player profiles in the Segment can be downloaded. Given below is an example of an Index file.
There are 2 URLs (export fragments) in the Index file.

Step 4:
Download the player profiles from each URL by iterating through the lines in the Index file. The player profile
files use tsv formatting. For example, the player profile downloaded from the first URL in the above Index file is
given below:
What is A/B testing?
5/24/2022 • 3 minutes to read • Edit Online

A/B testing is a technique for running experiments to determine the optimal setting for a particular variable. For
example, let’s say you want to test out different sale prices for an item in your in-game store.
With A/B testing, you create a series of player “buckets” into which you partition your players randomly, with
weights assigned to each bucket. Each bucket is assigned a different price. Players see the price assigned to their
bucket. You then compare the results for each bucket, to determine the most effective price.
The following table of values gives you an example of what this might look like.

VA RIA B L E A B C

Weight 50% 25% 25%

Price per item $1.99 $2.99 $4.99

Total users 10,020 4,996 5,025

% paying users 2.1% 2.0% 1.8%

Revenue $418 $298 $451

ARPU $0.0417 $0.0596 $0.0898

Here, bucket “C”, despite having the highest price, ended up generating the higher Average Revenue Per User
(ARPU), and would appear to be the “winner” of the test.

How PlayFab Supports A/B Testing


We are building support for A/B testing on top of our player segmentation feature of PlayStream. Each test
bucket is implemented as a player segment. So if you are running an A/B test called “Price Test” with two
buckets, “A” and “B”, then we will create two new segments, “Price Test - A” and “Price Test - B”. All players will be
automatically assigned to one of these two segments, based on the bucket weights you selected.
Today, the only feature in PlayFab that can directly show different players different results based on segment is
the targeted store override feature of the in-game economy. Effectively, this means the only thing you can A/B
test today are stores (including both prices, and collection of items).
However, we will soon be adding the ability for other PlayFab features to target different data to different players
- such as title data.
Once a test is turned on, we will start generating a daily report for basic Key Performance Indicators (KPIs),
based on buckets. This will allow you to determine the effectiveness of your tests. Later, we will make it possible
to do more detailed analysis using an external analytics provider.

Creating your first A/B test


After signing into the PlayFab Game Manager , select the PlayStream tab, and then on the A/B testing sub-
tab.
From here, you can create your first A/B test. At test creation time, you’ll need to provide an A/B test name , the
Number of buckets , and a Name and Percentage (weight) for each bucket.
The weights must add up to 100, and the names must be unique. The corresponding segments are then
automatically named test name - bucket name. For example, Gem Price Test - Control.

Note that bucket assignment is probabilistic, so the populations of each bucket may vary by up to a few percent
of the specified weight. This evens out as your player base grows.

Hooking your test up to stores


Once your test is set up, head to the Stores sub-section of the Catalogs section in your Economy tab. From
here, you’ll be able to set overrides for a store on the Edit Store page.
See our store segment override blog for more details on this.

Reviewing Results
Once you’ve created a test, we will begin to generate a daily report referred to as the Daily A/B Test KPI Report.
This will give you key KPIs by player bucket for each test you are currently running.
We recommend letting this report run for at least a few days, to get a baseline before configuring store
overrides. We partition your users based on their PlayFab IDs, which are randomly assigned at creation time.
Due to the probabilistic assignment of players, it is unlikely that the KPI will be uniform at the beginning of the
test.
Once you're confident about the results of your test, you can then reconfigure your primary store and safely
delete the test.

Future Work on A/B Testing


Today, stores are the only PlayFab feature area that have segment overrides. We have plans for overriding Title
Data by segments - as well as other areas - in the immediate future.
This will look much like store overrides, where title-wide variables will be configurable, based on the segment of
the user requesting title data. This will allow for tuning a much wider variety of features for your title.
We also have plans to allow you to run A/B tests within an existing segment, instead of for all players. So, for
example, you could try running an A/B test on pricing, that applies only to members of the VIP segment.
Links
A/B testing quickstart
A/B testing tutorials
A/B testing quickstart
5/24/2022 • 2 minutes to read • Edit Online

This quickstart explains how to create A/B tests with player buckets.
A/B tests allow you to use the buckets as Player Segments. Unlike player segments, however, A/B buckets
distribute players randomly. The buckets defined for these tests may then be used in some of the features,
where you would normally use player segments.
For an example of this, see our tutorial A/B Testing with Stores and A/B Test Buckets.

Creating an A/B test


A/B tests are created through the PlayFab Game Manager. Open your Title page:
1. Select Automation from the left-hand menu.
2. Move to the A/B Testing tab.
3. Select the NEW A/B TEST button. The New A/B Test dialog appears.
4. Fill in the A/B Test Name .
5. Set the number of buckets for your player groups.
6. Name each Bucket you define and select a percentage of Players that belong to the Bucket .
7. Select the SAVE A/B TEST button to submit the test.
The workflow is illustrated in the following picture.
The A/B Testing page will open and a newly created Test will appear in the list (shown below).

Links
To dive deeper into A/B testing, read the following tutorials:
A/B Testing with Stores and test buckets
A/B Testing with Title data
A/B Testing Tutorials
5/24/2022 • 2 minutes to read • Edit Online

In these tutorials you learn how to set up A/B tests.


A/B Testing with Stores and test buckets
A/B Testing with Title data
A/B testing with stores and test buckets
5/24/2022 • 2 minutes to read • Edit Online

In our Stores and Sales tutorial, we demonstrate how to set up a store and make a few items available to a
player at special or alternate prices.
In our A/B Testing quickstart, we demonstrate how to create A/B tests and form player buckets for random,
percentage-based user distribution.
This tutorial lets you combine these features, and produce several versions of the store available to different A/B
testing groups (buckets).
We first define an A/B test. In this case we define a test called Store A/B Testing, which splits users into 3 groups.
The first group (control) contains 34% of all the players. The other 2 test groups each contain 33% of all players,
as shown in the example provided below.

Next, we create one store to be the original version, and then create 3 other stores, which are A/B tested
variations of the original.
Each store is created independently, has its own unique identifier, and should have content that is customized for
that segment (see below).
Return to the original Store page:
Locate the SEGMENT OVERRIDES section.
It will not only contain the usual Player Segments , but it will also expose all the Buckets for all A/B Tests
that you currently have.
Make sure your A/B Test Buckets are on the top of the list, and assign Store override settings for each Bucket ,
as shown in the following picture.

Do not forget to save the settings. You have an A/B test where players are distributed into 3 groups of 50% ,
30% and 20% .
For each group of players, you assign a different version of the store. You may then use A/B testing reports to
track user conversion for each version of the store.
Best practices for store segmentation
Please consult the following tutorial: Best practices for Store Segmentation.
A/B testing with TitleData, A/B test buckets, and
CloudScript
5/24/2022 • 5 minutes to read • Edit Online

This tutorial illustrates how to complement PlayFab's built-in features with something which is not a fully
integrated feature yet.
A/B Testing title data is a planned feature. However, It is possible to build your own solution now , using
CloudScript.

Requirements
Writing Custom CloudScript, and CloudScript quickstart
Title Data
A/B Testing quickstart

Optional Requirements
The final example uses Unity, but this technique can be used with any SDK.

General idea and implementation


We already have a built-in feature defining A/B segments for a player (described in the A/B Testing quickstart).
Let's reuse those segments to return title data, based on which bucket our player belongs to.
First, we will need an A/B test. Please, follow the A/B Testing quickstart to create an A/B test. Once the test is
created, you will see the IDs of each of the individual Buckets , as shown below.

Functionally, a bucket ID is the same as a normal segment ID. An API call to GetPlayerSegments will return both
segment IDs and A/B test bucket IDs.
We can use this to our advantage, and introduce a convention for A/B-Tested title data keys, as shown below.
First, we introduce a regular entry with the Key called MyMessage .
We then introduce an A/B -version for each Bucket . The Key is composed using the original Key and a suffix
in the form _BUCKETID .
At any point in time, if we are given an original key and segment ID, we can easily compose a key that is
entry-specific for this segment/bucket.
Our next step is defining one more entry - a list of all the bucket IDs participating in the testing. In this case
we have three of those, as shown below.

NOTE
Make sure to use double quotes ( " ). Otherwise, the JavaScript runtime will not be able to parse it properly.

Now let us define a brand new API call using CloudScript. This API call is named GetTitleDataAB , and performs a
very simple procedure:
1. We receive a regular title data key (ex. MyMessage ) from the client, via args.
2. We get all the bucket IDs participating in the testing.
We do this by reading the TitleDataAbTestSegmentIds key from our title data.
3. We get all the segment IDs a player belongs to.
We do this by making a call to GetPlayerSegments and passing the current player ID.
4. If a player does not belong to any bucket, we return the value for the original key:
For example, MyMessage -> This is normal message .
5. If a player belongs to one of the tested segments, we assemble a new key using our convention, and try
to fetch the value for this key:
For example, if a player belongs to a bucket with the ID 920BD7F496ACB328 , we read the value for the
MyMessage_920BD7F496ACB328 key.
6. If no bucket-specific value was defined, we, again, return the value for the original key.
Let's inspect the following implementation (please read the code comments for further explanation).
// Special key in the Title Data that contains an array of AB buckets that participate in the testing
var TITLE_AB_TEST_TITLE_KEY = "TitleDataAbTestSegmentIds";
handlers.GetTitleDataAB = function (args, ctx) {
// The data key the player originally requested.
var dataKey = args.TitleKey;

// A variable to store AB segment of the player, if any


var currentAbTestSegmentId = null;

/*
* We store a list of bucket IDs that participate in the AB testing in the title data.
* This line extracts an array of such ids
*/
var requestedTitleData = server.GetTitleData({ Keys: [TITLE_AB_TEST_TITLE_KEY, dataKey] });
var defaultValue = requestedTitleData.Data.hasOwnProperty(dataKey) ? requestedTitleData.Data[dataKey] :
null;
var segmentIdJson = requestedTitleData.Data.hasOwnProperty(TITLE_AB_TEST_TITLE_KEY) ?
requestedTitleData.Data[TITLE_AB_TEST_TITLE_KEY] : null;
var abTestSegmentIds = JSON.parse(segmentIdJson);

// This line extracts all the segments current player belongs to


var playerSegments = server.GetPlayerSegments({ PlayFabId: currentPlayerId }).Segments;

// Locate first ABTest segment the player belongs to


for (var i = 0; i < playerSegments.length; i++) {
var playerSegmentId = playerSegments[i].Id;
if (abTestSegmentIds.indexOf(playerSegmentId) !== -1)
currentAbTestSegmentId = playerSegmentId;
}

// If player does not belong to any tested segment, return a value for the original key
if (!currentAbTestSegmentId)
return defaultValue;

/*
* If player belongs to one of AB tested segments
* we use ID of this segment to construct special key
* First part of this key is the original key
* Followed by underscore ('-') we add a suffix, which is ID of the bucket the player belongs to.
*/
var abTestedKey = dataKey + "_" + currentAbTestSegmentId;

// We try to get a value using our special key


var result = server.GetTitleData({ Keys: [abTestedKey] });
if (result.Data[abTestedKey])
return result.Data[abTestedKey];
else
return defaultValue;
};

Testing
Once the CloudScript from the previous section is uploaded, the code snippet shown below can be used to test
the described technique.

public void GetContent() {


PlayFabClientAPI.ExecuteCloudScript(new ExecuteCloudScriptRequest {
FunctionName = "GetTitleDataAB",
FunctionParameter = new Dictionary<string, string>() { { "TitleKey", "MyMessage" } },
},
result => Debug.Log(JsonWrapper.SerializeObject(result.FunctionResult)),
error => Debug.LogError(error.GenerateErrorReport()));
}
[Optional] Demonstration (with Unity)
Follow the steps in our CloudScript quickstart to deploy the CloudScript sample to your PlayFab title.
Once this is done, open a new Unity project. Make sure you have the PlayFab SDK imported, and the title setting
configured.
Create an empty scene and an empty game object. Attach the script that follows to the game object.

// Import statements to gain reference to all PlayFab classes we need


using System.Collections;
using System.Collections.Generic;
using PlayFab;
using PlayFab.ClientModels;
using UnityEngine;

public class PlayerABTestingTitle : MonoBehaviour {


// We simply start coroutine on start
public void Start() {
StartCoroutine(ABTester());
}

private IEnumerator ABTester() {


// Repeat 10 times
for (int i = 0; i < 10; i++) {
// Waiting flags
bool isLoggedIn = false;
bool isAbDataFetched = false;

// First, we log as a certain "fake" player using custom ID.


// The player is different with each iteration, as custom ID includes the value of "i"
PlayFabClientAPI.LoginWithCustomID(new LoginWithCustomIDRequest {
CustomId = "CustomID-"+i,
CreateAccount = true
}, result =>
{
// Once we are logged in, set the log in waiting flag to true
isLoggedIn = true;
Debug.Log("Logged in as Player "+i);
},OnError);

// Coroutine will wait here, until we set log in waiting flag to true
while(!isLoggedIn) yield return null;

// Secondly, we execute CloudScript call to our function called "GetTitleDataAB"


// We pass in TitleKey. In this example, it is "MyMessage"
PlayFabClientAPI.ExecuteCloudScript(new ExecuteCloudScriptRequest {
FunctionName = "GetTitleDataAB",
FunctionParameter = new Dictionary<string, string>() { { "TitleKey", "MyMessage" } },

}, result =>
{
// Once data is obtained, we set isAbDataFetched to true and log the result
isAbDataFetched = true;
Debug.Log(result.FunctionResult);
},OnError);

while(!isAbDataFetched) yield return null;


}
}

private void OnError(PlayFabError obj) {


Debug.LogError(obj.GenerateErrorReport());
}
}
Start the scene and open the console. If everything is configured properly, you will see how the application is
signing into PlayFab using different player accounts, and we get different title data fetched each time.

At this point, you can use this implementation to A/B test any data in your title.
Getting started with business intelligence
5/24/2022 • 2 minutes to read • Edit Online

Getting to know your players and their behavioral patterns in your game is critical to increasing retention,
engagement and monetization.
The goal of this document is to help you get up to speed on how PlayFab empowers your business intelligence,
and to quickly immerse you in the tool sets that we provide.

NOTE
Before you can use Game Manager for your title, you need to create a PlayFab Developer Account.

In general, you can analyze what players are doing in your game by following their event patterns. In PlayFab,
these come from PlayStream events.
PlayStream is an event processing system that unifies the entire data flow from your game into a single event
stream. You can then visualize and take actions on that stream in real time.

Getting to know your players through Game Manager


Real time events are amazing and actionable. But sometimes you need to perform deeper analytics over a
period of time to get retention - or a better understanding of how your players are engaging with your game.
For this, we offer a variety of solutions. Let's begin by talking about our built-in tools in Game Manager, which is
our online portal to your game title.
You can learn more about Game Manager here.
In Game Manager, you can search for events, view reports, and look at specific data about each player and their
actions.
Here are some resources to get you started with the Event Viewer:
Real-Time Analytics: Core Concepts - Gives you precise insights into what is going on inside your game.
Built in Analytic Reports - Gets reports on daily, monthly and rolling overviews, track retention and
conversion reports, and view reports on your top spenders and purchases.
Getting to know your players outside of Game Manager
While PlayFab provides some awesome tools for getting to know your players, sometimes you may need a bit
more customization.
PlayFab has a number of ways to reach your data outside of our Game Manager tool set. For this, we offer
several ways to export data into various systems.
Here are a few great ways to access your data:
S3 Event Archiving – PlayFab allows you to archive the entire event flow by using an Amazon S3 bucket.
This guide shows step-by-step how to configure event archiving from scratch.
Snowflake – See the entire event flow in Snowflake, for deep analytics query power.
Webhooks - In complex systems you may want to provide additional event handling on your custom
server. PlayFab offers Webhooks to achieve this. Whenever a new event is detected, it can be forwarded
to your server by making a POST request to your custom web endpoint, and the event data is passed as
the JSON body of the request.
PlayFab Insights (preview) - PlayFab Insights is a premium PlayFab offering that provides a central
repository for your data, whether it's generated from our services or imported from an external source.
Getting started for developers
5/24/2022 • 4 minutes to read • Edit Online

Thank you for either choosing PlayFab as your platform for back-end services and LiveOps or evaluating the
PlayFab offering. Welcome!
The first step in adding PlayFab to any Title is adding code to authenticate and log in the player. Logging in the
player returns a security token that is needed for all other API calls.
In this topic we show you how to retrieve the TitleId for your Title. You can then follow the quickstart guides
listed later on in this topic to learn how to use the TitleId to log a player in.

NOTE
The quickstart guides use a test TitleId . When you follow a guide, use a TitleId for a Title that you have created in your
PlayFab Developer account.

Before you can make your first API call to log a player in, you must create a PlayFab Developer account.

Retrieving your TitleId


When you create a Title in Game Manager, PlayFab generates a TitleId that identifies your Title. When following
the guides, use a TitleId for a Title that you have created.
For information about using Game Manager and creating a Title, see Game Manager quickstart.
To retrieve the TitleId for your Title, log in to the Game Manager.
On the My Studios and Titles screen, locate your Title. The TitleId is located just below the name of your Title.

Login and account basics


Now that you have retrieved a Title in Game Manager and retrieved your TitleId , you're ready to make API calls.
The starting point for any PlayFab integration is authentication. You must authenticate your player to make
further API calls.
Here are some resources to help you with the initial authentication of your player:
Login basics and Best Practices – Check this tutorial first to learn about the best practices to use various
authentication methods in your Title.
Platform-Specific Authentication – Use these guides to understand the basics of authentication calls into
PlayFab.
Account Linking tutorial - Learn about linking and unlinking different types of accounts to a single player
profile.

Calling the PlayFab API to log in


To allow you to integrate PlayFab into your Title, we provide SDKs, libraries, and extensions for the most popular
game engines, frameworks, and platforms.
Select the SDK and appropriate quickstart guide for your preferred environment. The quickstart guide walks
through installing the SDK into your environment, creating a new test project, and making your first API call. To
get started, see SDK overview.

Using PlayFab services to instrument your Title


Mapping your Title on top of PlayFab is a great start. But there is more power to be harnessed in PlayFab that
can help your LiveOps team create better engagement, retention, and monetization mechanics.
Many of these features leverage PlayStream, an event system that drives real time events. This enables you to
perform actions on player behaviors. Actions can occur in several ways - using either segmentation or direct
rules that are applied to specific events.
Actions might result in a CloudScript being run. Our CloudScript is JavaScript code that lives on a remote server,
and you can execute it either from a rule, or directly from a client.
For more information, check out these resources to get you started with Cloud Scripting and Automation on
PlayFab:
Automation – A hub for information on CloudScript, Scheduled Tasks, PlayStream and Action & Rules.
CloudScript quickstart – Get up and running quickly with your first CloudScript call.

TIP
To leverage rules in the automation system, write custom events in your Title which creates a PlayStream event. For more
information on custom events, see Custom event overview in Generating PlayStream events.

Next steps
Every Title is different, so you will have a unique set of features that you must build every time. It is important to
know and understand how to map those features onto PlayFab.
This generally starts with the configuration of your Title. You will want to store variables in PlayFab and pull
them down on to game clients. But these are not the only types of configurations that you'll want to make.
Some of the different ways that you can map PlayFab onto a Title are shown below; use these to find the
combination of tools that is just right for your Title:
Title Data – Map variables containing data on PlayFab to data structures in your game clients.
Entity Objects (aka: Player Data) – Store and retrieve data on a per player basis.
Catalogs (Items) - Very useful for storing configuration data about your Items and potentially being able to
sell them as virtual goods.
Groups – Groups are generally used for things like guilds or clans. Groups are arbitrary and have members,
roles and other guild-like features.
Finally, check out each of our feature areas in the links provided below to find the right feature set for your Title:
Authentication
Data
Automation
Social
Economy
Multiplayer
Analytics
Engagement
PlayFab Pricing Overview
5/24/2022 • 2 minutes to read • Edit Online

WARNING
PlayFab customers on the legacy pricing model (MAU based pricing) will need to update their account plans to the
modern pricing model prior to 10/31/2020 at which time MAU based pricing will no longer be supported. Learn how
to update your account .

Want to learn more about PlayFab pricing? The following articles can help you understand PlayFab's
pricing model, how to view your estimated bill, and how to manage account upgrades and titles launches
through Game Manager. View the most up-to-date offers and prices at PlayFab.com/Pricing.
1. Billing Summar y : View past and present estimated costs.
2. Development Mode : Understand technical limits applied to titles in development mode.
3. Pricing Meters : Learn about meter pricing and related APIs.
4. Multiplayer Ser ver Pricing : Learn about multiplayer server (MPS) pricing when MPS is enabled.
5. Par ty Pricing : Learn about Party pricing when Party is enabled.
6. User Generated Content Pricing : Learn about User Generated Content (UGC) pricing when UGC is
enabled.
7. Experiments Pricing : Learn about Experiments pricing when used.
8. Technical Suppor t : Access support included in paid account plans.
9. Upgrading Accounts : Upgrade your account plan using the self-serve plans experience in Game
Manager.
10. Launching Titles : Launch your titles in Game Manager.
Billing Summary and Base Rate
5/24/2022 • 4 minutes to read • Edit Online

Admin or billing permissions are required to view the Billing Summar y page.
The billing details page provides a daily snapshot of your month-to-date estimate charges. Use the information
on this page to estimate what your bill will look like at the end of the month and view past months to
understand trends and comparisons. The billing details page helps you determine what the biggest consumers
of your metered resources are and gives you information that you can use to reduce your charges in
subsequent months.

NOTE
The values reported on the billing summary page are an estimate of usage and associated costs for an account. The
amount shown might not depict the final invoice amount charged to an account.

To view the billing details page for your studio navigate to the My Studios and Titles page. Click the ellipsis on
the right side of your studio, and then selecting the Billing summary option in the drop-down.

Billing Summary Overview

1. Last Refreshed Date


This is the date or time that the billing summary page was last refreshed. The billing details page is
refreshed on a daily basis.
2. Selected Month
This is the month that the listed consumption and charges cover. Use the Month Filter (8) to change
the selected month.
3. Month-To-Date (MTD) Estimated Charge
This is the daily snapshot of estimated total charges that your studio has accrued during the selected
calendar month.
4. The Fine Print
Only use the Billing Summar y page as an estimate for your month-to-date charges. Some meters
have a 48+ hour delay and the Billing Summar y page does not include all chargeable items (For
example, Add-ons). On the first of the current month, you can view the final estimate for the previous
month's charges (excluding taxes and delayed meter charges), and on the second of the current
month, you can view the first estimate for the current month's usage and costs.
5. .csv Download
You can download the Billing Summar y view to .csv for further analysis. The "Download Summary"
provides the same granularity as the Billing Summar y page. The "Download daily" provides the the
daily breakdown of usage.

NOTE
As the storage meters are billed based off average consumption instead of total consumption, the data is
represented differently. The first day of data contains the MTD average, and the remainder of the days are
purposefully left blank.

6. Contact Information
This is the contact information we use to send you an invoice. This can be changed by navigating to
the Billing Information page.
7. Title Filter
Use the Title filter to understand consumption and apportioned cost by title. Namespace events are
counted in the "All" calculation, but aren't currently available to drill down (as they aren't tied to a title).
Development mode titles are not charged to the account and do not display cost data.
8. Month Filter
Use this filter to choose the month to display. All billing summary data from the time the account was
updated to usage-based pricing is visible through the billing summary page.
9. Meter Categor y
The Pay as you Go section buckets the full set of meters into logical categories. You can find the full
set of meters in meter documentation.
10. Meter
This is a billable meter that at least one of your titles is consuming. You only see meters that you are
using. For a full list of meters, see meter documentation.
11. Usage
This column provides estimated, rounded usage (for readability purposes) for each tier/SKU, as well as
the aggregated amount. To see the exact usage, download the .csv (5).
12. Rate
This column provides the rounded rates (for readability purposes) for each tier/SKU. To see the exact
rates, please download the .csv (5).
13. Cost
This column provides the estimated cost for each tier/SKU, as well as the aggregated amount.
14. Description
Each meter provides a brief description in the billing summary page. You can find a more detailed
explanation of the meters in meter documentation.

Understanding the Base Rate


Base Rate: The base rate is the standard, monthly rate for paid accounts.
The base rate charge includes:
1. Meter usage amounts that are specified at Playfab.com/Pricing. Once meter usage across live titles
associated to an account has surpassed the included amounts (above), an account's live title usage will be
charged based on the meter rates found at PlayFab.com/Pricing (also listed under the "Rate" column on the
Billing Summary page). These costs are referred to as "Pay-As-You-Go" charges.

NOTE
Titles in Development Mode are not counted against included base rate usage.

2. Technical suppor t that is determined by the account level.

Additional Section Definitions


Pay-As-You-Go Charges: Pay-As-You-Go charges are the cost of individual meter usage per title in an account
that exceed usage amounts that are part of the plan. The per-meter prices can be found at Playfab.com/Pricing
or under the "Rate" column on the billing summary page.
Additional Charges: Additional charges include any charges not directly tied to the meter-usage pricing plan.
For example, charges for MPS and Add-Ons may appear in the additional charges section.
Learn More

Multiplayer Server Pricing


Party Pricing
Titles in Development Mode
5/24/2022 • 2 minutes to read • Edit Online

All PlayFab titles are in one of two possible states - development mode and live. Development Mode is, as the
name suggests, meant for titles currently in development. This mode provides developers with the flexibility to
connect a title to PlayFab without running up the bill. However, there are functional limitations for titles in
development mode (detailed below). A title in development mode can only have up to 100k users. These titles
can be launched through Game Manager and is then considered live. Launching a title removes all development
mode limitations and allows the title to expand outside of test markets.
By default, every title created starts in development mode. The My Studios and Titles main page will indicate
which state a title is in through a mark on the bottom, left corner of the title block. This indicator can also be
viewed at the top of the left nav within a title. Titles in development mode are labeled Development . Live titles
are blank.
My Studios view of development mode title tag

Title page view of development mode title tag

Live title with blank tag


NOTE
As long as your title is in development mode, consumption is not counted towards any of your billable meters.

The following walks you through an example of a fictional customer called Fun Studios:

T IT L E T IT L E M O DE M ET ER C O N SUM P T IO N

Fun Game Live 1M PlayStream Events

Fun Game 2: The Return of Fun Development Mode 100K PlayStream Events

When Fun Studios visits their Billing Summary page, they only see the consumption for their Live title, Fun
Game, count against their Standard Plan included resources.
For more information on these topics, check out these pages:
Meters
Upgrades
Billing Summary

Limits
There are some studio and title limits associated with development mode:
Studio Limits
L IM IT A M O UN T

Titles in Development Mode 10 Titles

Title Limits
L IM IT A M O UN T

Unique Users 100,000 Users

PlayStream Events 1M Events

Telemetry Events 1M Events

Profile Reads 5M Reads

Profile Writes 1M Writes


L IM IT A M O UN T

Profile Storage 2 GB

Content and Configuration Reads 20K Reads

Content and Configuration Writes 15K Writes

Content and Configuration Storage 2 GB

CloudScript Execution Time 20K GB-s

CloudScript Total Executions 200K Executions

Insights Credits Insights Performance Level 1

Definition of Unique Users: Unique Users are simply the total amount of player profiles you have in your
title, which is different from MAU - you can delete player profiles through the Players page in Game Manager to
reduce the total number of Unique Users if you are approaching the limit but aren't ready to launch your title

NOTE
You can learn more about title limits at PlayFab.com/Pricing page.
Pricing Meters
5/24/2022 • 6 minutes to read • Edit Online

PlayFab's pricing is calculated from a set of consumption-based meters. This page outlines and defines the full
set of PlayFab's pricing meters and how they are measured and calculated. For more information on PlayFab's
pricing model, see PlayFab Pricing Overview.

NOTE
This page does not include Add-ons like Community Sift, Snowflake, or Photon, and is subject to change as new services
and capabilities are added to PlayFab.

Core Meters
PlayFab Events, Profile, and Content & Configuration are the services that make up the core PlayFab product.
Most PlayFab features use of a mix of functionality across the core services and will accrue usage against one or
more core meters.
Events
View and take action on your game's real-time data. Events can be generated in two ways. Standard events are
automatically generated by PlayFab Game Services APIs and written to the event pipeline. Custom events can be
created to trigger specific actions within the event pipeline.
PlayStream Events - PlayStream unifies your game data into a single stream and allows you to trigger
player engagement actions. These events show up in the PlayStream Monitor to provide real time
visualization of event data. For more information, see PlayStream Event Model reference.
Telemetr y Events - Telemetry events are custom events that bypass PlayStream and go straight to the data
warehouse. For more information, see PlayStream Events - Write Telemetry Events.

[!NOTE] Events are metered in 1 KB blocks against average event size. For example, 10 events with an
average size of 2 KB are billed as 20 events, while 10 events with an average size of 0.5 KB are billed as 10
events.

Example: Weighted Events Calculation


To get a better understanding of how weighted meters are calculated, let's take a look at a sample title's
PlayStream Events consumption for the previous month:

EVEN T N A M E C O UN T SIZ E

player_leveled_up 40 50KB

player_bought_item 30 10KB

player_statistic_changed 20 30KB

player_executed_cloudscript 10 20KB

By adding up the total size (110KB) and dividing by the total count (100), we get an average size of 1.1KB.
Therefore, we need to multiply the total count by 1.1 to get the effective count of 110 PlayStream Events. Let's
look at the same example with some adjusted numbers:

EVEN T N A M E C O UN T SIZ E

player_leveled_up 40 40KB

player_bought_item 30 10KB

player_statistic_changed 20 20KB

player_executed_cloudscript 10 20KB

By adding up the total size (90KB) and dividing by the total count (100), we get an average size of 0.9KB.
Therefore, we don't multiply the total count by anything - we stick with 100 PlayStream Events, even though the
player_executed_cloudscript event had an average size larger than 1KB.
Profile
There is nothing more important to the success of your games than your players. The Profile is what helps you
understand and engage with your players - it includes any stored data related to player profile, entity profile,
character profile, groups membership, and inventory. Data reads, writes, and storage are billed as part of this
metered service.
Reads - Metered based on the total number of reads to profile data which are processed by PlayFab. For a
list of read APIs, see Profile read APIs. This meter is weighted to 1KB.
Writes - Metered based on the total number of writes (and deletes) which are processed by PlayFab. For a
list of write APIs, see Profile write APIs. This meter is weighted to 1KB.
Storage - Metered based on the average total volume of profile data hosted by PlayFab across daily
snapshots.
Content & Configuration
Content & Configuration files are used to remotely manage configuration for your game. You can update game
content remotely in real-time (or on a schedule), and deliver personalized news and events that keep players
coming back for more. Content & Configuration files include the following items: entity files, actions, rules,
scheduled tasks, matchmaking, push notifications, emails, and title news. Content & Configuration files are a set
of key/value pairs that are primarily used to manage configuration for your game remotely. Files data reads,
writes, and storage are billed as part of this metered service.
Reads - Metered based on the total number of files data reads which are processed by PlayFab. For a list of
read APIs, see Content & Configuration read APIs. This meter is weighted to 10KB.
Writes - Metered based on the total number of files data writes (and deletes) which are processed by
PlayFab. For a list of write APIs, see Content & Configuration write APIs.
Storage - Metered based on the average total volume of files data hosted by PlayFab across daily snapshots.

Service-specific Meters
The following services are metered directly in addition to any usage they accrue against core meters.
CloudScript
CloudScript enables you to use client code to request execution of any custom server-side functionality you can
implement. It enables you to build server-side logic and functionality that scales to meet your demand, without
worrying about servers or infrastructure. Both total number of CloudScript executions and corresponding
execution time, are billed as part of this metered service.
Execution Time - CloudScript execution time is metered based on the per-second resource consumption
across all CloudScript executions, measured in GB-s (average memory size in GBs x total execution time in
milliseconds).

NOTE
The minimum billable memory size and execution time per execution is 128MB and 100ms, respectively.

Total Executions - Total number of ExecuteFunction API calls that are processed by PlayFab, including ones
triggered by actions, rules, and scheduled tasks. For more information on the ways executions can occur, see
Server-Side Cloud Script - Execution Function, Actions & Rules, and Scheduled Tasks.
Insights
Real-time analytics give you immediate insight into a game's performance and potential issues. Insights include
services such as the performance of the data warehouse, long-term storage of data, custom visualization
technology, managed external data sources or specialized data projects. The total combined usage of Insights
products, represented by an aggregate value ("Insights Credits"), is billed as part of this metered service. Insight
Credits are derived from conversion rates for usage of each Insight services.
Insights Credits - The total number of Insights Credits used across all Insights products. For a detailed
breakdown of how Insights Credits are calculated, see Insights Pricing.
Multiplayer Servers
PlayFab Multiplayer Servers deliver secure and reliable low-latency gameplay at global scale. Multiplayer
Servers facilitate interoperable multiplayer infrastructure and cross-network gameplay, and allow you to
operate a dynamically scaling pool of custom game servers in Azure.
Vir tual Machine Instance Hours - The hours of virtual machine time that your game servers use,
including overhead hours generated by standby servers and virtual machine fragmentation. Price varies by
datacenter, virtual machine and container selection. For more information, see Multiplayer Servers detailed
price sheet.
Network Egress - The volume of data transmitted by your game servers to the Internet (in
gigabytes). Network egress is billed depending on the originating datacenter. Price varies by zone.
Party
PlayFab Party is a low-latency chat and data communication solution for cross-platform and cross-device
multiplayer games. The voice and text features in Party can be used as a standalone chat solution or in
conjunction with other features in PlayFab's Multiplayer product. There are four key meters used to bill Party
utilization:
Connectivity : Metered by number of player minutes connected to a network. Metering starts when a player
creates a network or joins a network, and it stops when they have disconnected.
Voice : Metered by number of player minutes speaking. When a player is connected to a network and is
actively speaking, that player voice activity is measured and metered.
Cognitive Ser vices : Metered by number of player minutes using Speech to Text, Text to Speech, or
Translation features.
Network Egress This is data sent from PlayFab's relay and voice servers. This is congruent to the aggregate
amount of data that players receive from the network.

NOTE
Party Network Egress is metered and priced separately from Multiplayer Servers Network Egress.

Additional resources
For the most up-to-date view of prices per meter, see PlayFab.com/Pricing
See Consumption Best Practices to learn how to maintain the lowest rate of meter usage and cost for your
game
Profile Reads
5/24/2022 • 14 minutes to read • Edit Online

Profile includes any data stored related to the player profile, entity profile, character profile, groups, and
inventory. Profile data is information that applies to an individual player, group of players, or items, and is stored
as Key/Value Pairs (KVPs) by PlayFab.
The following APIs cause the Profile read meter to increment.

Admin APIs
CheckLimitedEditionItemAvailability Checks the global count for the limited edition item.
GetAllSegments Retrieves an array of player segment definitions. Results from this can be used in
subsequent API calls such as GetPlayersInSegment which requires a Segment ID. While segment names
can change the ID for that segment will not change.
ExportMasterPlayerData Exports all associated data of a master player account.
GetCatalogItems Retrieves the specified version of the title's catalog of virtual goods, including all defined
properties.
GetContentList List all contents of the title and get statistics such as size.
GetDataReport Retrieves a download URL for the requested report.
GetPlayerSegments List all segments that a player currently belongs to at this moment in time.
GetPlayerTags Get all tags with a given Namespace (optional) from a player profile.
GetPolicy Gets the requested policy.
GetPublisherData Retrieves the key-value store of custom publisher settings.
GetRandomResultTables Retrieves the random drop table configuration for the title.
GetStoreItems Retrieves the set of items defined for the specified store, including all prices defined.
GetTitleData Retrieves the key-value store of custom title settings which can be read by the client.
[GetUserAccountInfo](Retrieves the relevant details for a specified user, based upon a match against a
supplied unique identifier) Retrieves the relevant details for a specified user, based upon a match against
a supplied unique identifier.
GetUserBans Gets all bans for a user.
GetUserData Retrieves the title-specific custom data for the user which is readable and writable by the
client.
GetUserInternalData Retrieves the title-specific custom data for the user which cannot be accessed by the
client.
GetUserInventory Retrieves the specified user's current inventory of virtual goods
GetUserPublisherData Retrieves the publisher-specific custom data for the user which is readable and
writable by the client.
GetUserPublisherInternalData Retrieves the publisher-specific custom data for the user which cannot be
accessed by the client.
GetUserPublisherReadOnlyData Retrieves the publisher-specific custom data for the user which can only
be read by the client.
GetUserReadOnlyData Retrieves the title-specific custom data for the user which can only be read by the
client.
ListVirtualCurrencyTypes Retuns the list of all defined virtual currencies for the title
GetMatchmakerGameInfo Retrieves the details for a specific completed session, including links to
standard out and standard error logs.
GetMatchmakerGameModes Retrieves the details of defined game modes for the specified game server
executable.
GetPlayerIdFromAuthToken Gets a player's ID from an auth token.
GetPlayersInSegment Allows for paging through all players in a given segment. This API creates a
snapshot of all player profiles that match the segment definition at the time of its creation and lives
through the Total Seconds to Live, refreshing its life span on each subsequent use of the Continuation
Token. Profiles that change during the course of paging will not be reflected in the results. AB Test
segments are currently not supported by this operation.
GetExperiments Gets the details of all experiments for a title.
GetLatestScorecard Gets the latest scorecard of the experiment for the title.
GetTreatmentAssignment Gets the treatment assignments for a player for every running experiment in
the title

Client APIs
GetAllUsersCharacters Lists all of the characters that belong to a specific user. CharacterIds are not
globally unique; characterId must be evaluated with the parent PlayFabId to guarantee uniqueness.
GetCatalogItems Retrieves the specified version of the title's catalog of virtual goods, including all defined
properties.
GetCharacterData Retrieves the title-specific custom data for the character which is readable and writable
by the client.
GetCharacterInventory Retrieves the specified character's current inventory of virtual goods.
GetCharacterLeaderboard Retrieves a list of ranked characters for the given statistic, starting from the
indicated point in the leaderboard.
GetCharacterReadOnlyData Retrieves the title-specific custom data for the character which can only be
read by the client.
GetCharacterStatistics Retrieves the details of all title-specific statistics for the user.
GetFriendLeaderboard Retrieves a list of ranked friends of the current player for the given statistic,
starting from the indicated point in the leaderboard.
GetFriendLeaderboardAroundPlayer Retrieves a list of ranked friends of the current player for the given
statistic, centered on the requested PlayFab user. If PlayFabId is empty or null will return currently logged
in user.
GetFriendsList Retrieves the current friend list for the local user, constrained to users who have PlayFab
accounts. Friends from linked accounts (Facebook, Steam) are also included. You may optionally exclude
some linked services' friends.
GetGameServerRegions Get details about the regions hosting game servers matching the given
parameters.
GetLeaderboard Retrieves a list of ranked users for the given statistic, starting from the indicated point in
the leaderboard.
GetLeaderboardAroundCharacter Retrieves a list of ranked characters for the given statistic, centered on
the requested Character ID.
GetLeaderboardAroundPlayer Retrieves a list of ranked users for the given statistic, centered on the
requested player. If PlayFabId is empty or null will return currently logged in user.
GetLeaderboardForUserCharacters Retrieves a list of all of the user's characters for the given statistic.
GetPaymentToken For payments flows where the provider requires playfab (the fulfiller) to initiate the
transaction, but the client completes the rest of the flow. In the Xsolla case, the token returned here will be
passed to Xsolla by the client to create a cart. Poll GetPurchase using the returned OrderId once you've
completed the payment.
GetPlayerProfile Retrieves the player's profile.
GetPlayerSegments List all segments that a player currently belongs to at this moment in time.
GetPlayerStatistics Retrieves the indicated statistics (current version and values for all statistics, if none
are specified), for the local player.
GetPlayerStatisticVersions Retrieves the information on the available versions of the specified statistic.
GetPlayerTags Get all tags with a given Namespace (optional) from a player profile.
GetPlayerTrades Gets all trades the player has either opened or accepted, optionally filtered by trade
status.
GetPlayFabIDsFromFacebookIDs Retrieves the unique PlayFab identifiers for the given set of Facebook
identifiers.
GetPlayFabIDsFromFacebookInstantGamesIds Retrieves the unique PlayFab identifiers for the given set of
Facebook Instant Game identifiers.
GetPlayFabIDsFromGameCenterIDs Retrieves the unique PlayFab identifiers for the given set of Game
Center identifiers (referenced in the Game Center Programming Guide as the Player Identifier).
GetPlayFabIDsFromGenericIDs Retrieves the unique PlayFab identifiers for the given set of generic service
identifiers. A generic identifier is the service name plus the service-specific ID for the player, as specified
by the title when the generic identifier was added to the player account.
GetPlayFabIDsFromGoogleIDs Retrieves the unique PlayFab identifiers for the given set of Google
identifiers. The Google identifiers are the IDs for the user accounts, available as "id" in the Google+
People API calls.
GetPlayFabIDsFromKongregateIDs Retrieves the unique PlayFab identifiers for the given set of
Kongregate identifiers. The Kongregate identifiers are the IDs for the user accounts, available as "user_id"
from the Kongregate API methods(ex: http://developers.kongregate.com/docs/client/getUserId).
GetPlayFabIDsFromNintendoSwitchDeviceIds Retrieves the unique PlayFab identifiers for the given set of
Nintendo Switch identifiers.
GetPlayFabIDsFromPSNAccountIDs Retrieves the unique PlayFab identifiers for the given set of
PlayStation Network identifiers.
GetPlayFabIDsFromSteamIDs Retrieves the unique PlayFab identifiers for the given set of Steam
identifiers. The Steam identifiers are the profile IDs for the user accounts, available as SteamId in the
Steamworks Community API calls.
GetPlayFabIDsFromTwitchIDs Retrieves the unique PlayFab identifiers for the given set of Twitch
identifiers. The Twitch identifiers are the IDs for the user accounts, available as "_id" from the Twitch API
methods (ex: https://github.com/justintv/Twitch-API/blob/master/v3_resources/users.md#get-usersuser).
GetPlayFabIDsFromXboxLiveIDs Retrieves the unique PlayFab identifiers for the given set of XboxLive
identifiers.
GetPublisherData Retrieves the key-value store of custom publisher settings.
GetPurchase Retrieves a purchase along with its current PlayFab status. Returns inventory items from the
purchase that are still active.
GetSharedGroupData Retrieves data stored in a shared group object, as well as the list of members in the
group. Non-members of the group may use this to retrieve group data, including membership, but they
will not receive data for keys marked as private. Shared Groups are designed for sharing data between a
very small number of players, see Using Shared Group Data.
GetStoreItems Retrieves the set of items defined for the specified store, including all prices defined.
GetTitleData Retrieves the key-value store of custom title settings
GetAccountInfo Retrieves the user's PlayFab account details.
LoginWithAndroidDeviceID Signs the user in using the Android device identifier, returning a session
identifier that can subsequently be used for API calls which require an authenticated user.
LoginWithCustomID Signs the user in using a custom unique identifier generated by the title, returning a
session identifier that can subsequently be used for API calls which require an authenticated user
LoginWithEmailAddress Signs the user into the PlayFab account, returning a session identifier that can
subsequently be used for API calls which require an authenticated user. Unlike most other login API calls,
LoginWithEmailAddress does not permit the creation of new accounts via the CreateAccountFlag. Email
addresses may be used to create accounts via RegisterPlayFabUser.
LoginWithFacebook Signs the user in using a Facebook access token, returning a session identifier that
can subsequently be used for API calls which require an authenticated user.
LoginWithFacebookInstantGamesId Signs the user in using a Facebook Instant Games ID, returning a
session identifier that can subsequently be used for API calls which require an authenticated user.
Requires Facebook Instant Games to be configured.
LoginWithGameCenter Signs the user in using an iOS Game Center player identifier, returning a session
identifier that can subsequently be used for API calls which require an authenticated user.
LoginWithGoogleAccount Signs the user in using an iOS Game Center player identifier, returning a
session identifier that can subsequently be used for API calls which require an authenticated user.
LoginWithIOSDeviceID Signs the user in using their Google account credentials.
LoginWithKongregate Signs the user in using a Kongregate player account.
LoginWithNintendoSwitchDeviceId Signs the user in using a Nintendo Switch Device ID, returning a
session identifier that can subsequently be used for API calls which require an authenticated user.
LoginWithOpenIdConnect Logs in a user with an Open ID Connect JWT created by an existing
relationship between a title and an Open ID Connect provider.
LoginWithPlayFab which require an authenticated user. Unlike most other login API calls,
LoginWithPlayFab does not permit the creation of new accounts via the CreateAccountFlag.
Username/Password credentials may be used to create accounts via RegisterPlayFabUser, or added to
existing accounts using AddUsernamePassword.
LoginWithPSN Signs the user into the PlayFab account, returning a session identifier that can
subsequently be used for API calls which require an authenticated user. Unlike most other login API calls,
LoginWithPlayFab does not permit the creation of new accounts via the CreateAccountFlag.
Username/Password credentials may be used to create accounts via RegisterPlayFabUser, or added to
existing accounts using AddUsernamePassword.
LoginWithSteam Signs the user in using a Steam authentication ticket, returning a session identifier that
can subsequently be used for API calls which require an authenticated user.
LoginWithTwitch Signs the user in using a Twitch access token.
LoginWithXbox Signs the user in using a Xbox Live Token, returning a session identifier that can
subsequently be used for API calls which require an authenticated user.
GetCurrentGames Get details about all current running game servers matching the given parameters.
GetPlayerCombinedInfo Retrieves all of the user's different kinds of info.

Data APIs
GetObjects Retrieves objects from an entity's profile.

Groups APIs
GetGroup Gets information about a group and its roles.
IsMember Checks to see if an entity is a member of a group or role within the group.
ListGroupApplications Lists all outstanding requests to join a group.
ListGroupBlocks Lists all entities blocked from joining a group.
ListGroupInvitations Lists all outstanding invitations for a group.
ListGroupMembers Lists all members for a group.
ListMembership Lists all groups and roles for an entity.
ListMembershipOpportunities Lists all outstanding invitations and group applications for an entity.

Profile APIs
GetGlobalPolicy Gets the global title access policy.
GetProfile Retrieves the entity's profile.
GetProfiles Retrieves the entity's profile.
GetTitlePlayersFromMasterPlayerAccountIds Retrieves the title player accounts associated with the given
master player account.

Server APIs
EvaluateRandomResultTable Returns the result of an evaluation of a Random Result Table - the ItemId
from the game Catalog which would have been added to the player inventory, if the Random Result Table
were added via a Bundle or a call to UnlockContainer.
GetAllSegments Retrieves an array of player segment definitions. Results from this can be used in
subsequent API calls such as GetPlayersInSegment which requires a Segment ID. While segment names
can change the ID for that segment will not change.
GetAllUsersCharacters Lists all of the characters that belong to a specific user. CharacterIds are not
globally unique; characterId must be evaluated with the parent PlayFabId to guarantee uniqueness.
GetCatalogItems Retrieves the specified version of the title's catalog of virtual goods, including all defined
properties.
GetCharacterData Retrieves the title-specific custom data for the user which is readable and writable by
the client.
GetCharacterInternalData Retrieves the title-specific custom data for the user's character which cannot be
accessed by the client.
GetCharacterInventory Retrieves the specified character's current inventory of virtual goods.
GetCharacterReadOnlyData
GetCharacterStatistics Retrieves the details of all title-specific statistics for the specific character.
GetFriendLeaderboard Retrieves a list of ranked friends of the given player for the given statistic, starting
from the indicated point in the leaderboard.
GetFriendsList Retrieves the current friends for the user with PlayFabId, constrained to users who have
PlayFab accounts. Friends from linked accounts (Facebook, Steam) are also included. You may optionally
exclude some linked services' friends.
GetLeaderboard Retrieves a list of ranked users for the given statistic, starting from the indicated point in
the leaderboard.
GetLeaderboardAroundCharacter Retrieves a list of ranked characters for the given statistic, centered on
the requested user.
GetLeaderboardAroundUser Retrieves a list of ranked characters for the given statistic, centered on the
requested user.
GetLeaderboardForUserCharacters Retrieves a list of all of the user's characters for the given statistic.
GetPlayerCombinedInfo Returns whatever info is requested in the response for the user. Note that PII (like
email address, facebook id) may be returned. All parameters default to false.
GetPlayerProfile Retrieves the player's profile.
GetPlayerSegments List all segments that a player currently belongs to at this moment in time.
GetPlayersInSegment Allows for paging through all players in a given segment. This API creates a
snapshot of all player profiles that match the segment definition at the time of its creation and lives
through the Total Seconds to Live, refreshing its life span on each subsequent use of the Continuation
Token. Profiles that change during the course of paging will not be reflected in the results. AB Test
segments are currently not supported by this operation.
GetPlayerStatistics Retrieves the current version and values for the indicated statistics, for the local player.
GetPlayerStatisticVersions Retrieves the information on the available versions of the specified statistic.
GetPlayerTags Get all tags with a given Namespace (optional) from a player profile.
GetPlayFabIDsFromFacebookIDs Retrieves the unique PlayFab identifiers for the given set of Facebook
identifiers.
GetPlayFabIDsFromFacebookInstantGamesIds Retrieves the unique PlayFab identifiers for the given set of
Facebook identifiers.
GetPlayFabIDsFromGenericIDs Retrieves the unique PlayFab identifiers for the given set of generic service
identifiers. A generic identifier is the service name plus the service-specific ID for the player, as specified
by the title when the generic identifier was added to the player account.
GetPlayFabIDsFromNintendoSwitchDeviceIds Retrieves the unique PlayFab identifiers for the given set of
Nintendo Switch Device identifiers.
GetPlayFabIDsFromPSNAccountIDs Retrieves the unique PlayFab identifiers for the given set of
PlayStation Network identifiers.
GetPlayFabIDsFromSteamIDs Retrieves the unique PlayFab identifiers for the given set of Steam
identifiers. The Steam identifiers are the profile IDs for the user accounts, available as SteamId in the
Steamworks Community API calls.
GetPlayFabIDsFromXboxLiveIDs Retrieves the unique PlayFab identifiers for the given set of XboxLive
identifiers.
GetPublisherData Retrieves the key-value store of custom publisher settings.
GetRandomResultTables Retrieves the configuration information for the specified random results tables
for the title, including all ItemId values and weights.
GetServerCustomIDsFromPlayFabIDs Retrieves the associated PlayFab account identifiers for the given
set of server custom identifiers.
GetSharedGroupData Retrieves data stored in a shared group object, as well as the list of members in the
group. The server can access all public and private group data. Shared Groups are designed for sharing
data between a very small number of players, see Using Shared Group Data.
GetStoreItems Retrieves the set of items defined for the specified store, including all prices defined, for
the specified player.
GetTitleData Retrieves the key-value store of custom title settings.
GetTitleInternalData Retrieves the key-value store of custom internal title settings.
GetUserAccountInfo Retrieves the relevant details for a specified user.
GetUserBans Gets all bans for a user.
GetUserData Retrieves the title-specific custom data for the user which is readable and writable by the
client.
GetUserInternalData Retrieves the title-specific custom data for the user which cannot be accessed by the
client.
GetUserInventory Retrieves the specified user's current inventory of virtual goods.
GetUserPublisherData Retrieves the publisher-specific custom data for the user which is readable and
writable by the client.
GetUserPublisherInternalData Retrieves the publisher-specific custom data for the user which cannot be
accessed by the client.
GetUserPublisherReadOnlyData
GetUserReadOnlyData Updates the title-specific custom data for the user which can only be read by the
client.
LoginWithServerCustomId Securely login a game client from an external server backend using a custom
identifier for that player. Server Custom ID and Client Custom ID are mutually exclusive and cannot be
used to retrieve the same player account.
LoginWithXbox Signs the user in using a Xbox Live Token from an external server backend, returning a
session identifier that can subsequently be used for API calls which require an authenticated user.
LoginWithXboxId Signs the user in using an Xbox ID and Sandbox ID, returning a session identifier that
can subsequently be used for API calls which require an authenticated user.
Profile Writes
5/24/2022 • 17 minutes to read • Edit Online

Profile includes any data stored related to the player profile, entity profile, character profile, groups, and
inventory. Profile data is information that applies to an individual player, group of players, or items, and is stored
as Key/Value Pairs (KVPs) by PlayFab.
The following APIs cause the Profile writes meter to increment.

Admin APIs
AddPlayerTag Adds a given tag to a player profile. The tag's namespace is automatically generated based
on the source of the tag.
AddUserVirtualCurrency Increments the specified virtual currency by the stated amount
AddVirtualCurrencyTypes Adds one or more virtual currencies to the set defined for the title. Virtual
Currencies have a maximum value of 2,147,483,647 when granted to a player. Any value over that will be
discarded.
BanUsers Bans users by PlayFab ID with optional IP address, or MAC address for the provided game.
CreateActionsOnPlayersInSegmentTask Create an ActionsOnPlayersInSegment task, which iterates
through all players in a segment to execute action.
CreatePlayerSharedSecret Creates a new Player Shared Secret Key. It may take up to 5 minutes for this
key to become generally available after this API returns.
CreatePlayerStatisticDefinition Adds a new player statistic configuration to the title, optionally allowing
the developer to specify a reset interval and an aggregation method.
DeleteMasterPlayerAccount Removes a master player account entirely from all titles and deletes all
associated data.
DeletePlayer Removes a user's player account from a title and deletes all associated data
DeletePlayerSharedSecret Deletes an existing Player Shared Secret Key. It may take up to 5 minutes for
this delete to be reflected after this API returns.
DeleteStore Deletes an existing virtual item store.
DeleteTitle Permanently deletes a title and all associated configuration.
GrantItemsToUsers Adds the specified items to the specified user inventories
IncrementLimitedEditionItemAvailability Increases the global count for the given scarce resource.
IncrementPlayerStatisticVersion Resets the indicated statistic, removing all player entries for it and
backing up the old values.
RefundPurchase Attempts to process an order refund through the origin'l real money payment provider.""
RemovePlayerTag Remove a given tag from a player profile. The tag's namespace is automatically
generated based on the source of the tag.
RemoveVirtualCurrencyTypes Removes one or more virtual currencies from the set defined for the title.
ResetCharacterStatistics Completely removes all statistics for the specified character, for the current game.
ResetUserStatistics Completely removes all statistics for the specified user, for the current game.
ResolvePurchaseDispute Attempts to resolve a dispute with the original order's payment provider.
RevokeAllBansForUser Revoke all active bans for a user.
RevokeBans Revoke all active bans specified with BanId.
RevokeInventoryItem Revokes access to an item in a user's inventory
RevokeInventoryItems Revokes access for up to 25 items across multiple users and characters.
SetCatalogItems Creates the catalog configuration of all virtual goods for the specified catalog version.
SetPlayerSecret Sets or resets the player's secret. Player secrets are used to sign API requests.
SetPublishedRevision Sets the currently published revision of a title Cloud Script.
SetPublisherData Updates the key-value store of custom publisher settings
SetStoreItems Sets all the items in one virtual store.
SetTitleData Creates and updates the key-value store of custom title settings which can be read by the
client.
SetTitleInternalData Updates the key-value store of custom title settings which cannot be read by the
client.
SubtractUserVirtualCurrency Decrements the specified virtual currency by the stated amount.
UpdateBans Updates information of a list of existing bans specified with Ban Ids.
UpdateCatalogItems Updates the catalog configuration for virtual goods in the specified catalog version.
UpdatePlayerSharedSecret Updates a existing Player Shared Secret Key. It may take up to 5 minutes for
this update to become generally available after this API returns.
UpdatePlayerStatisticDefinition Updates a player statistic configuration for the title, optionally allowing
the developer to specify a reset interval.
UpdateRandomResultTables Updates the random drop table configuration for the title
UpdateStoreItems Updates an existing virtual item store with new or modified items.
UpdateUserData Updates the title-specific custom data for the user which is readable and writable by the
client.
UpdateUserInternalData Updates the title-specific custom data for the user which cannot be accessed by
the client.
UpdateUserPublisherData Updates the publisher-specific custom data for the user which is readable and
writable by the client.
UpdateUserPublisherInternalData Updates the publisher-specific custom data for the user which cannot
be accessed by the client.
UpdateUserPublisherReadOnlyData Updates the publisher-specific custom data for the user which can
only be read by the client.
UpdateUserReadOnlyData Updates the title-specific custom data for the user which can only be read by
the client.
UpdateUserTitleDisplayName Updates the title specific display name for a user.

Client APIs
AcceptTrade Accepts an open trade (one that has not yet been accepted or cancelled), if the locally signed-
in player is in the allowed player list for the trade, or it is open to all players. If the call is successful, the
offered and accepted items will be swapped between the two players' inventories.
AddFriend Adds the PlayFab user, based upon a match against a supplied unique identifier, to the friend
list of the local user. At least one of FriendPlayFabId,FriendUsername,FriendEmail, or
FriendTitleDisplayName should be initialized.
AddGenericID Adds the specified generic service identifier to the player's PlayFab account. This is
designed to allow for a PlayFab ID lookup of any arbitrary service identifier a title wants to add. This
identifier should never be used as authentication credentials, as the intent is that it is easily accessible by
other players.
AddOrUpdateContactEmail Adds or updates a contact email to the player's profile.
AddSharedGroupMembers Adds users to the set of those able to update both the shared data, as well as
the set of users in the group. Only users in the group (and the server) can add new members. Shared
Groups are designed for sharing data between a very small number of players, see Using Shared Group
Data.
AddUsernamePassword Adds playfab username/password auth to an existing account created via an
anonymous auth method, e.g. automatic device ID login.
AndroidDevicePushNotificationRegistration Registers the Android device to receive push notifications
ConsumePSNEntitlements Checks for any new consumable entitlements. If any are found, they are
consumed and added as PlayFab items.
ConsumeXboxEntitlements Grants the player's current entitlements from Xbox Live, consuming all
availble items in Xbox and granting them to the player's PlayFab inventory. This call is idempotent and
will not grant previously granted items to the player.
CreateSharedGroup Requests the creation of a shared group object, containing key/value pairs which
may be updated by all members of the group. Upon creation, the current user will be the only member of
the group. Shared Groups are designed for sharing data between a very small number of players. For
more info, see Using Shared Group Data.
GrantCharacterToUser Grants the specified character type to the user. CharacterIds are not globally
unique; characterId must be evaluated with the parent PlayFabId to guarantee uniqueness.
LinkAndroidDeviceID Links the Android device identifier to the user's PlayFab account
LinkCustomID Links the custom identifier, generated by the title, to the user's PlayFab account.
LinkFacebookAccount Links the Facebook account associated with the provided Facebook access token to
the user's PlayFab account.
LinkFacebookInstantGamesId Links the Facebook Instant Games Id to the user's PlayFab account.
LinkGameCenterAccount Links the Game Center account associated with the provided Game Center ID to
the user's PlayFab account.
LinkGoogleAccount Links the currently signed-in user account to their Google account, using their
Google account credentials.
LinkIOSDeviceID Links the vendor-specific iOS device identifier to the user's PlayFab account.
LinkKongregate Links the Kongregate identifier to the user's PlayFab account.
LinkNintendoSwitchDeviceId Links the NintendoSwitchDeviceId to the user's PlayFab account.
LinkOpenIdConnect Links an OpenID Connect account to a user's PlayFab account, based on an existing
relationship between a title and an Open ID Connect provider and the OpenId Connect JWT from that
provider.
LinkPSNAccount Links the PlayStation Network account associated with the provided access code to the
user's PlayFab account.
LinkSteamAccount Links the Steam account associated with the provided Steam authentication ticket to
the user's PlayFab account.
LinkTwitch Links the Twitch account associated with the token to the user's PlayFab account.
LinkWindowsHello Link Windows Hello authentication to the current PlayFab Account.
LinkXboxAccount Links the Xbox Live account associated with the provided access code to the user's
PlayFab account.
OpenTrade Opens a new outstanding trade. Note that a given item instance may only be in one open
trade at a time.
PurchaseItem Buys a single item with virtual currency. You must specify both the virtual currency to use
to purchase, as well as what the client believes the price to be. This lets the server fail the purchase if the
price has changed.
PayForPurchase Selects a payment option for purchase order created via StartPurchase
RegisterForIOSPushNotification Registers the iOS device to receive push notifications
RegisterPlayFabUser Registers a new Playfab user account, returning a session identifier that can
subsequently be used for API calls which require an authenticated user. You must supply either a
username or an email address.
RegisterWithWindowsHello Registers a new PlayFab user account using Windows Hello authentication,
returning a session ticket that can subsequently be used for API calls which require an authenticated user
RemoveContactEmail Removes a contact email from the player's profile.
RemoveFriend Removes a specified user from the friend list of the local user.
RemoveGenericID Removes the specified generic service identifier from the player's PlayFab account.
RemoveSharedGroupMembers Removes users from the set of those able to update the shared data and
the set of users in the group. Only users in the group can remove members. If as a result of the call, zero
users remain with access, the group and its associated data will be deleted. Shared Groups are designed
for sharing data between a very small number of players, see Using Shared Group Data.
ReportAdActivity Report player's ad activity
ReportDeviceInfo Write a PlayStream event to describe the provided player device information. This API
method is not designed to be called directly by developers. Each PlayFab client SDK will eventually report
this information automatically.
ReportPlayer Submit a report for another player (due to bad bahavior, etc.), so that customer service
representatives for the title can take action concerning potentially toxic players.
RestoreIOSPurchases Restores all in-app purchases based on the given restore receipt
SetFriendTags Updates the tag list for a specified user in the friend list of the local user.
SubtractUserVirtualCurrency Decrements the user's balance of the specified virtual currency by the
stated amount. It is possible to make a VC balance negative with this API.
UnlinkAndroidDeviceID Unlinks the related Android device identifier from the user's PlayFab account.
UnlinkCustomID Unlinks the related custom identifier from the user's PlayFab account.
UnlinkFacebookAccount Unlinks the related Facebook account from the user's PlayFab account.
UnlinkFacebookInstantGamesId Unlinks the related Facebook Instant Game Ids from the user's PlayFab
account.
UnlinkGameCenterAccount Unlinks the related Game Center account from the user's PlayFab account.
UnlinkGoogleAccount Unlinks the related Google account from the user's PlayFab account
(https://developers.google.com/android/reference/com/google/android/gms/auth/GoogleAuthUtil#publi
c-methods).
UnlinkIOSDeviceID Unlinks the related iOS device identifier from the user's PlayFab account.
UnlinkKongregate Unlinks the related Kongregate identifier from the user's PlayFab account.
UnlinkNintendoSwitchDeviceId Unlinks the related NintendoSwitchDeviceId from the user's PlayFab
account.
UnlinkOpenIdConnect Unlinks an OpenID Connect account from a user's PlayFab account, based on the
connection ID of an existing relationship between a title and an Open ID Connect provider.
UnlinkPSNAccount Unlinks the related PSN account from the user's PlayFab account.
UnlinkSteamAccount Unlinks the related Steam account from the user's PlayFab account.
UnlinkTwitch Unlinks the related Twitch account from the user's PlayFab account.
UnlinkWindowsHello Unlink Windows Hello authentication from the current PlayFab Account.
UnlinkXboxAccount Unlinks the related Xbox Live account from the user's PlayFab account.
UnlockContainerInstance Opens the specified container, with the specified key (when required), and
returns the contents of the opened container. If the container (and key when relevant) are consumable
(RemainingUses > 0), their RemainingUses will be decremented, consistent with the operation of
ConsumeItem.
UnlockContainerItem Searches target inventory for an ItemInstance matching the given CatalogItemId, if
necessary unlocks it using an appropriate key, and returns the contents of the opened container. If the
container (and key when relevant) are consumable (RemainingUses > 0), their RemainingUses will be
decremented, consistent with the operation of ConsumeItem.
UpdateAvatarUrl Update the avatar URL of the player.
UpdateCharacterData Creates and updates the title-specific custom data for the user's character which is
readable and writable by the client
UpdateCharacterStatistics Updates the values of the specified title-specific statistics for the specific
character. By default, clients are not permitted to update statistics. Developers may override this setting in
the Game Manager > Settings > API Features.
UpdatePlayerStatistics Updates the values of the specified title-specific statistics for the user. By default,
clients are not permitted to update statistics. Developers may override this setting in the Game Manager
> Settings > API Features.
UpdateSharedGroupData Adds, updates, and removes data keys for a shared group object. If the
permission is set to Public, all fields updated or added in this call will be readable by users not in the
group. By default, data permissions are set to Private. Regardless of the permission setting, only members
of the group can update the data. Shared Groups are designed for sharing data between a very small
number of players, see Using Shared Group Data.
UpdateUserData Creates and updates the title-specific custom data for the user which is readable and
writable by the client.
UpdateUserPublisherData Creates and updates the publisher-specific custom data for the user which is
readable and writable by the client.
UpdateUserTitleDisplayName Updates the title specific display name for the user

Data APIs
SetObjects Sets objects on an entity's profile.

Groups APIs
AcceptGroupApplication Accepts an outstanding invitation to to join a group
AcceptGroupInvitation Accepts an invitation to join a group.
AddMembers Adds members to a group or role.
ApplyToGroup Applies to join a group.
BlockEntity Blocks a list of entities from joining a group.
ChangeMemberRole Changes the role membership of a list of entities from one role to another.
CreateGroup Creates a new group.
CreateRole Creates a new group role.
DeleteGroup Deletes a group and all roles, invitations, join requests, and blocks associated with it.
DeleteRole Deletes an existing role in a group.
InviteToGroup Invites a player to join a group,
RemoveGroupApplication Removes an application to join a group.
RemoveGroupInvitation Removes an invitation join a group.
RemoveMembers Removes members from a group.
UnblockEntity Unblocks a list of entities from joining a group.
UpdateGroup Updates non-membership data about a group.
UpdateRole Updates metadata about a role.

Profile APIs
SetGlobalPolicy Sets the global title access policy.
SetProfileLanguage Updates the entity's language. The precedence hierarchy for communication to the
player is Title Player Account language, Master Player Account language, and then title default language if
the first two aren't set or supported.
SetProfilePolicy Sets the profiles access policy.
Server APIs
AddCharacterVirtualCurrency Increments the character's balance of the specified virtual currency by the
stated amount.
AddFriend Adds the Friend user to the friendlist of the user with PlayFabId. At least one of
FriendPlayFabId,FriendUsername,FriendEmail, or FriendTitleDisplayName should be initialized.
AddGenericID Adds the specified generic service identifier to the player's PlayFab account. This is
designed to allow for a PlayFab ID lookup of any arbitrary service identifier a title wants to add. This
identifier should never be used as authentication credentials, as the intent is that it is easily accessible by
other players.
AddPlayerTag Adds a given tag to a player profile. The tag's namespace is automatically generated based
on the source of the tag.
AddSharedGroupMembers Adds users to the set of those able to update both the shared data, as well as
the set of users in the group. Only users in the group (and the server) can add new members. Shared
Groups are designed for sharing data between a very small number of players, see Using Shared Group
Data.
AddUserVirtualCurrency Increments the user's balance of the specified virtual currency by the stated
amount.
AwardSteamAchievement Awards the specified users the specified Steam achievements.
BanUsers Bans users by PlayFab ID with optional IP address, or MAC address for the provided game.
ConsumeItem Consume uses of a consumable item. When all uses are consumed, it will be removed
from the player's inventory.
CreateSharedGroup Requests the creation of a shared group object, containing key/value pairs which
may be updated by all members of the group. When created by a server, the group will initially have no
members. Shared Groups are designed for sharing data between a very small number of players, see
Using Shared Group Data.
DeleteCharacterFromUser Deletes the specific character ID from the specified user.
DeleteSharedGroup Deletes a shared group, freeing up the shared group ID to be reused for a new
group. Shared Groups are designed for sharing data between a very small number of players, see Using
Shared Group Data.
GrantCharacterToUser Grants the specified character type to the user. CharacterIds are not globally
unique; characterId must be evaluated with the parent PlayFabId to guarantee uniqueness.
GrantItemsToCharacter Adds the specified items to the specified character's inventory.
GrantItemsToUser Adds the specified items to the specified user's inventory.
GrantItemsToUsers Adds the specified items to the specified user inventories,
LinkServerCustomId Links the custom server identifier, generated by the title, to the user's PlayFab
account.
LinkXboxAccount Links the Xbox Live account associated with the provided access code to the user's
PlayFab account.
ModifyItemUses Modifies the number of remaining uses of a player's inventory item.
MoveItemToCharacterFromCharacter Moves an item from a character's inventory into another of the
users's character's inventory.
MoveItemToCharacterFromUser Moves an item from a user's inventory into their character's inventory.
MoveItemToUserFromCharacter Moves an item from a character's inventory into the owning user's
inventory.
NotifyMatchmakerPlayerLeft Informs the PlayFab match-making service that the user specified has left
the Game Server Instance.
RedeemCoupon Adds the virtual goods associated with the coupon to the user's inventory. Coupons can
be generated via the Economy->Catalogs tab in the PlayFab Game Manager.
RedeemMatchmakerTicket Validates a Game Server session ticket and returns details about the user.
RemoveFriend Removes the specified friend from the user's friend list.
RemoveGenericID Removes the specified generic service identifier from the player's PlayFab account.
RemovePlayerTag Remove a given tag from a player profile. The tag's namespace is automatically
generated based on the source of the tag.
RemoveSharedGroupMembers Removes users from the set of those able to update the shared data and
the set of users in the group. Only users in the group can remove members. If as a result of the call, zero
users remain with access, the group and its associated data will be deleted. Shared Groups are designed
for sharing data between a very small number of players, see Using Shared Group Data.
RevokeAllBansForUser Revoke all active bans for a user.
RevokeBans Revoke all active bans specified with BanId.
RevokeInventoryItem Revokes access to an item in a user's inventory.
RevokeInventoryItems Revokes access for up to 25 items across multiple users and characters.
SetFriendTags Updates the tag list for a specified user in the friend list of another user.
SetPlayerSecret Sets the player's secret if it is not already set. Player secrets are used to sign API requests.
To reset a player's secret use the Admin or Server API method SetPlayerSecret.
SetPublisherData Updates the key-value store of custom publisher settings.
SetTitleData /rest/api/playfab/server/title-wide-data-management/setpublisherdata?
SetTitleInternalData Updates the key-value store of custom title settings
SubtractCharacterVirtualCurrency Decrements the character's balance of the specified virtual currency by
the stated amount. It is possible to make a VC balance negative with this API.
SubtractUserVirtualCurrency Decrements the user's balance of the specified virtual currency by the
stated amount. It is possible to make a VC balance negative with this API.
UnlinkServerCustomId Unlinks the custom server identifier from the user's PlayFab account.
UnlinkXboxAccount Unlinks the related Xbox Live account from the user's PlayFab account.
UnlockContainerInstance Opens a specific container (ContainerItemInstanceId), with a specific key
(KeyItemInstanceId, when required), and returns the contents of the opened container. If the container
(and key when relevant) are consumable (RemainingUses > 0), their RemainingUses will be decremented,
consistent with the operation of ConsumeItem.
UnlockContainerItem Searches Player or Character inventory for any ItemInstance matching the given
CatalogItemId, if necessary unlocks it using any appropriate key, and returns the contents of the opened
container. If the container (and key when relevant) are consumable (RemainingUses > 0), their
RemainingUses will be decremented, consistent with the operation of ConsumeItem.
UpdateAvatarUrl Update the avatar URL of the specified player.
UpdateBans Updates information of a list of existing bans specified with Ban Ids.
UpdateCharacterData Updates the title-specific custom data for the user's character which is readable and
writable by the client.
UpdateCharacterInternalData Updates the title-specific custom data for the user's character which cannot
be accessed by the client.
UpdateCharacterReadOnlyData Updates the title-specific custom data for the user's character which can
only be read by the client.
UpdateCharacterStatistics Updates the values of the specified title-specific statistics for the specific
character.
UpdatePlayerStatistics Updates the values of the specified title-specific statistics for the user.
UpdateUserData Updates the title-specific custom data for the user which is readable and writable by the
client.
UpdateUserInternalData Updates the title-specific custom data for the user which cannot be accessed by
the client.
UpdateUserInventoryItemCustomData Updates the key-value pair data tagged to the specified item,
which is read-only from the client.
UpdateUserPublisherData Updates the publisher-specific custom data for the user which is readable and
writable by the client.
UpdateUserPublisherInternalData Updates the publisher-specific custom data for the user which cannot
be accessed by the client.
UpdateUserPublisherReadOnlyData Updates the publisher-specific custom data for the user which can
only be read by the client.
UpdateUserReadOnlyData Updates the title-specific custom data for the user which can only be read by
the client.
Content & Configuration Reads
5/24/2022 • 2 minutes to read • Edit Online

Content & Configuration files include the following items: entity files, actions, rules, scheduled tasks,
matchmaking, push notifications, emails, and title news. Content & Configuration files are a set of key/value
pairs that are primarily used to manage configuration for your game remotely.
The following APIs cause the Content & Configuration reads meter to increment.

Admin APIs
GetContentUploadUrl Retrieves the pre-signed URL for uploading a content file. A subsequent HTTP PUT
to the returned URL uploads the content. Also, please be aware that the Content service is specifically
PlayFab's CDN offering, for which standard CDN rates apply
GetActionsOnPlayersInSegmentTaskInstance Get information about a ActionsOnPlayersInSegment task
instance.

Client APIs
GetTitleNews Retrieves the title news feed, as configured in the developer portal.
GetContentDownloadUrl This API retrieves a pre-signed URL for accessing a content file for the title. A
subsequent HTTP GET to the returned URL will attempt to download the content. A HEAD query to the
returned URL will attempt to retrieve the metadata of the content. Note that a successful result does not
guarantee the existence of this content - if it has not been uploaded, the query to retrieve the data will
fail. See this post for more information:
https://community.playfab.com/hc/community/posts/205469488-How-to-upload-files-to-PlayFab-s-
Content-Service. Also, please be aware that the Content service is specifically PlayFab's CDN offering, for
which standard CDN rates apply.
GetPhotonAuthenticationToken Gets a Photon custom authentication token that can be used to securely
join the player into a Photon room. See
https://docs.microsoft.com/gaming/playfab/features/multiplayer/photon/quickstart for more details.
GetTitlePublicKey Returns the title's base 64 encoded RSA CSP blob.
GetTradeStatus Gets the current status of an existing trade.
GetWindowsHelloChallenge Requests a challenge from the server to be signed by Windows Hello
Passport service to authenticate.

Data APIs
GetFiles Retrieves file metadata from an entity's profile.

Server APIs
GetContentDownloadUrl This API retrieves a pre-signed URL for accessing a content file for the title. A
subsequent HTTP GET to the returned URL will attempt to download the content. A HEAD query to the
returned URL will attempt to retrieve the metadata of the content. Note that a successful result does not
guarantee the existence of this content - if it has not been uploaded, the query to retrieve the data will
fail. See this post for more information:
https://community.playfab.com/hc/community/posts/205469488-How-to-upload-files-to-PlayFab-s-
Content-Service. Also, please be aware that the Content service is specifically PlayFab's CDN offering, for
which standard CDN rates apply.
GetTitleNews Retrieves the title news feed, as configured in the developer portal.
SendCustomAccountRecoveryEmail Forces an email to be sent to the registered contact email address for
the user's account based on an account recovery email template.
SendEmailFromTemplate Sends an email based on an email template to a player's contact email.
SendPushNotification Sends an iOS/Android Push Notification to a specific user, if that user's device has
been configured for Push Notifications in PlayFab. If a user has linked both Android and iOS devices, both
will be notified.
SendPushNotificationFromTemplate Sends an iOS/Android Push Notification template to a specific user, if
that user's device has been configured for Push Notifications in PlayFab. If a user has linked both Android
and iOS devices, both will be notified.
Content & Configuration Writes
5/24/2022 • 2 minutes to read • Edit Online

Content & Configuration files include the following items: entity files, actions, rules, scheduled tasks,
matchmaking, push notifications, emails, and title news. Content & Configuration files are a set of key/value
pairs that are primarily used to manage configuration for your game remotely.
The following APIs cause the Content & Configuration writes meter to increment.

Admin APIs
AddLocalizedNews Update news item to include localized version
AddNews Adds a new news item to the title's news feed
DeleteContent Delete a content file from the title. When deleting a file that does not exist, it returns
success.
-ModifyMatchmakerGameModes Updates the game server mode details for the specified game server
executable
-ResetPassword Reset a player's password for a given title.
SetupPushNotification Sets the Amazon Resource Name (ARN) for iOS and Android push notifications.
Documentation on the exact restrictions can be found at:
http://docs.aws.amazon.com/sns/latest/api/API_CreatePlatformApplication.html. Currently, Amazon
device Messaging is not supported.
UpdatePolicy Changes a policy for a title

Data APIs
FinalizeFileUploads Finalize file uploads to an entity's profile.
DeleteFiles Delete files on an entity's profile.
InitiateFileUploads Initiates file uploads to an entity's profile.

Server APIs
DeletePushNotificationTemplate Deletes push notification template for title
SavePushNotificationTemplate Saves push notification template for title
Accessing PlayFab Technical Support
5/24/2022 • 2 minutes to read • Edit Online

To make integration with PlayFab as seamless and efficient as possible, PlayFab offers a variety of support
options ranging from online documentation to live conversations with PlayFab engineers. Different support
options are included in each account plan as determined by the tier of the account. Customers can upgrade their
accounts to access higher levels of support.

Support Offerings
PUBLIC DOCUMENTATION
Purpose: Use the PlayFab documentation to view service offerings, API functionality, and how-to guides.
Minimum Required Account Plan: No account needed, open to the public.
How to access: To view PlayFab documentation, see PlayFab Documentation.
PLAYFAB FORUMS
Purpose: The PlayFab Forums provide community based product support. Use the forums to post questions,
share answers, and discuss the PlayFab product experience..
Minimum Required Account Plan: No account needed to view, free PlayFab user account needed to post.
How to access: Anyone can read the forums. To contribute, you must sign in with your PlayFab account. To
access the forums, visit PlayFab Forums.
SUPPORT TICKET SUBMISSION
Purpose: Use support tickets to report a bug, to understand how to use a particular PlayFab feature, or to
request help with a technical problem. Customers with paid accounts may submit support tickets directly to the
PlayFab team through the "Contact Us" Page in Game Manager. Customers will receive a response within 1
business day.
Minimum Required Account Plan: Standard Account Plan
How to access: Qualified accounts can access the Contact Us page in Game Manager:
1. Log in to PlayFab.com.
2. Navigate to the Title Over view page of the title needing support.
3. To access the help menu, select the ? in the top right navigation bar.
4. Select Contact Us .
EMERGENCY ESCALATIONS
Purpose: To provide PlayFab's fastest incident response time to customers during emergencies by notifying on-
call PlayFab engineers.

NOTE
Emergency escalations should be used sparingly and only in the case of high-impact service errors or outtages.

Minimum Required Account Plan: Premium Account Plan


How to access: Qualified accounts can use the emergency escalation option via the Contact Us page in Game
Manager:
1. Log in to PlayFab.com.
2. Navigate to the Title Over view page of the title needing support.
3. Select the ? in the top right navigation bar to access the drop-down menu.
4. Select Contact Us to access the form. The Emergency On-Call Aler t option displays after completing the
Problem Type and Sub-Type fields.
5. To submit the ticket, select Yes .
To learn more about upgrading to a paid account plan, see Account Upgrades and Title Launches.
Updating an Account to Modern Pricing
5/24/2022 • 5 minutes to read • Edit Online

PlayFab customers on the legacy pricing model (MAU-based pricing) must update their account plans to the
modern pricing model (Usage-based pricing) prior to 11/01/2020 at which time MAU-based pricing will no
longer be supported.
Customers can understand changes to monthly costs and initiate their account's pricing update through the self-
serve experience in Game Manager (detailed below) or through contacting the PlayFab team.

Understanding how Existing Title Usage Translates into Modern


Pricing Costs
For some accounts moving to modern pricing, monthly costs may change due to a title's usage of PlayFab
features. To understand monthly costs on a modern pricing scale, customers can utilize the Billing Summary and
Pricing page.
The Billing Summar y page will allow customers to view meter usage by account or by title. Customers can
also use the page to understand if existing title usage is included in the modern pricing base rate.
The Pricing page will allow customers to view the cost of meter usage.

Self-Serve Account Transition to Modern Pricing


1. Log in to PlayFab.com.
2. From the My Studios and Titles page, select Update Pricing on the navigation bar of the Studio
whose billing account will move to usage-based pricing.
3. You will be directed to the Plan Recommendation page. On this page, you can see your rolling-thirty-
day usage. Based upon your historic usage, we will calculate your estimate bill for your current plan and
recommend the most cost-savings plan.
4. Select Proceed with plan to move to the Plan Selection page to pick a plan. The recommended plan
will be automatically selected, but you can select any plan you are elligble for.
5. Select Next to move through the contact information and payment information tabs.
6. Select Confirm this Plan from the review stage to complete the billing account update to usage-based
pricing.
To learn more about plans, see Account Upgrades

FAQ
Q. What will happen to my account on November 1st, 2020?
Customers already on usage-based pricing plans (Standard Plan, Premium Plan)
Nothing! You have already transitioned to our new pricing and you should experience business-as-usual.
Essentials customers
Essentials customers will be transitioned to the Free to Start Plan with their titles in Development Mode. As long
as your titles are in Development Mode, you can continue using PlayFab for free. You can have up to 10 titles in
Development Mode at a time, and Development Mode allows up to 100,000 users per title.
Once your first title reaches 100,000 users, you will need to upgrade your plan to add more users to your title.
Once you have upgraded, you will need to launch your title in order to have unlimited users.
If your account has a title with over 100k users, you will not be able to add any more users until you add a
payment plan or delete users to 100k or fewer. For some titles, this may disrupt the availability of your game for
new players, so you should understand which of your current titles are approaching or are above 100k users to
understand which are at risk.
If your account has more than 10 titles, you will not be able to add any new titles until you have either deleted
titles to total under 10, or you have upgraded your plan and launched titles so that you have no more than 10 in
Dev Mode.
We recommend selecting a plan prior to the transition date of November 1st, 2020 so that your game
availability is not disrupted.
Indie & Pro Tier customers
Indie and Pro customers will be automatically transitioned to the Standard plan, which has a monthly minimum
of $99, and includes monthly meters valued at $400 USD along with Gold Level Support, which is the same
support level as you received in the Indie and Pro Tiers. Therefore, you will continue to have Public Forum
access as well as, be able to submit support tickets as needed.
Those customers who need Platinum Support with emergency escalations or estimate heavier usage will be able
to self-upgrade (available in October) to the Premium Plan which includes monthly meters valued at $8,000
USD for only $1,999 USD per month.
Customers that estimate low title usage or who do not need ticketed support, can select the Pay-as-you-Go plan
with no monthly minimum (available in October). You will still have access to the Public Forums and can
upgrade your plan as you grow.
For more information, go to Accessing PlayFab technical support.
Q. I have not selected a plan, will my account be shut off?
No. Based on your current tier, your titles will either be transitioned to Dev Mode or the Standard Plan. However,
If you are an Essentials customers with titles with over 100k users, you will need to select a plan in order for new
users to play your game. We recommend understanding which of your titles are currently exceeding 100k users
so that you can select that plan that works best for you prior to the transition date of November 1, 2020.
Q. I am an Enterprise customer. What will happen to my account?
Enterprise accounts will be migrated to the new pricing plans according to their contract renewal date and will
not automatically transition on November 1. If you have questions about your Enterprise contract, email us at:
sales@playfab.com
Q. How can I understand the costs for my studio prior to the transition?
To preview the impact of moving your titles to consumption-based pricing, go to the Billing Summar y page by
selecting Studio settings from the My Studios and Titles homepage.
Q. It looks like I might save money with the new pricing. Do I have to wait until Nov. 1 before I make the transition?
No, you can upgrade your account to a new pricing plan at any time. To do so, select Update Pricing from your
My Studios and Titles homepage or Title's Dashboard.
Q: I can see my total meter usage in the billing summary, and I’ve read the best practices doc, but I’m still not sure how to figure
out where the costs are coming from in my title. What tools are available to figure out which specific API calls are the ones costing
me the most?
In addition to the API graph on the main dashboard of your game, which shows the overall traffic and can be
filtered to show each individual call and response, there’s also the Daily API Usage Details Report in the
Dashboards > Repor ts section of the Game Manager for your title. That report breaks down, on a per-hour
basis, the API calls made in the title, as well as the average and total bytes sent/returned hourly. So, for example,
the total calls to UpdateUserData will be shown for each hour, along with the total bytes sent, which allows
you to quickly calculate the expected meter usage (given that a Profile Write ticks the meter at a per KB rate for
data written).
Account Upgrades
5/24/2022 • 5 minutes to read • Edit Online

Customers can upgrade their account plan using the self-serve plans experience found in Game Manager.

Account Plans
A PlayFab account has five plan options:
1. FREE TO START : This plan has no cost to the customer. Studios that belong to free accounts may only
contain titles that are in development mode. Once a title reaches its development mode limits, it must be
launched by upgrading to a paid plan. To learn how to launch a title, see Title Launches.Once a title reaches its
development mode limits, it must be launched by upgrading to a paid plan. To learn how to launch a title, see
Title Launches.
2. PAY-AS-YOU-GO : This paid plan has no monthly base rate. Accounts are only charged for their monthly
consumption for live titles.
3. STANDARD : This paid plan has a monthly base rate and private support options (Paid Technical Support).
This plan comes with included meter usage amounts that live titles associated with the account may access.
Once the included meter amounts have been used, the account will be charged for additional consumption.
4. PREMIUM : This paid plan has a monthly base rate and private support options (Paid Technical Support).
This plan comes with more included meter usage than the Standard plan. Once the included meter amounts
have been used, the account will be charged for additional consumption.
5. ENTERPRISE : An Enterprise account has a monthly base rate and private support channels that offer 24/7
assistance. This plan comes with more included meter usage than the Premium plan. Once the included
meter amounts have been used, the account will be charged for additional consumption. An account can
upgrade to an Enterprise plan through contacting the PlayFab Team .
The base rate's included consumption is cumulative across titles linked to an account.

[! NOTE] All PlayFab account plans adhere to the PlayFab Terms of Service.

Understanding the Account-Studio-Title Relationship


An account is linked to one Studio and a Studio may be linked to many titles. Upgrades are executed at the
account level and launches are executed at the Title level.
Changing Plans
You can change your account's plan via Game Manager using the Plan Recommendation and Plan Selection
pages. Plan changes are scheduled for the beginning of the next billing period.
Upgrading from Free to Start
You can upgrade your account plan at any time on the My Studios and Titles page. Use the following steps to
upgrade your account from Free to Start. Upgrading an account will upgrade all studios owned by the account.
1. Log in to PlayFab.com.
2. On the My Studios and Titles page, locate the header of a Studio whose linked account should be
upgraded. Select Upgrade Account .
3. c. Through the Plan Recommendation page, you can see your account's meter usage for the past 30
days, your current plan, and a recommended plan based upon your usage. On each plan, you can see
the estimated monthly cost given your historic usage. To change your plan, select Proceed with plan .
4. On the Plan Selection page, the recommended plan will be automatically selected, though you can
select any plan your account is eligible for. Titles can be launched in conjunction with the plan change.
Select any titles to launch. The Next button will open the next tab.
5. Enter Contact Information and Payment Information to move to the Review page. Select Confirm this
Plan to complete the account upgrade.
6. Once you upgrade your account, on the Studio Settings page under the Studio Plan section, you will see
your current plan as well as the scheduled plan and date of schedyle.
After an account is upgraded, the provided payment instrument is charged a monthly base rate per account in
addition to usage charges for launched titles.
Upgrading and Downgrading
You can upgrade or downgrade your account plan at any time on the Studio Settings page of any studio owned
by the account. Use the following steps to change your account's plan. Changing the account plan will change all
studios owned by the account.
1. Log in to PlayFab.com.
2. On the My Studios and Titles page, locate the header of a Studio whose linked account should be
upgraded. Select the options button indicated by the 3 dots and select Studio Settings . On the Studio
Settings page, locate the header of a Studio whose linked account should be upgraded. Select Change
Plan .
3. c. Through the Plan Recommendation page, you can see your account's meter usage for the past 30
days, your current plan, and a recommended plan based upon your usage. On each plan, you can see
the estimated monthly cost given your historic usage. To change your plan, select Proceed with plan .
4. On the Plan Selection page, the recommended plan will be automatically selected, though you can
select any plan your account is eligible for. Titles can be launched in conjunction with the plan change.
Select any titles to launch. The Next button will open the next tab.
5. Enter Contact Information and Payment Information to move to the Review page. Select Confirm this
Plan to complete the account upgrade.
6. Once you upgrade your account, on the Studio Settings page under the Studio Plan section, you will see
your current plan as well as the scheduled plan.
Upgrading to Enterprise
Any account is eligible to upgrade to an Enterprise account plan. The PlayFab team must be contacted to
upgrade to an Enterprise account plan. Contact PlayFab

FAQ
How do I know which subscription plan my account and its associated studios are currently on?
There are two ways to know which plan your account is currently on.
1. Presence of Upgrade Account Button: Navigate to the "My Studios" page. If a Studio displays the
Upgrade Account button, the Studio and its associated account are currently free and have no account plan
(1).
2. Base Rate Amount: While on the "My Studios" page, if no "Upgrade Account" button is present, navigate to
the Billing Summar y page (3). A lack of the Upgrade Account button means that the Studio and its
associated account are on a paid subscription plan.
The amount of the base rate will represent the paid subscription plan of an account. A Base Rate of $99
indicates that the Studio and its associated account are on the Standard plan . A base rate of $1999 indicates
that the Studio and its associated account are on the Premium plan . The Premium plan can only be acquired
through contacting PlayFab.
How do I know which subscription plan I am upgrading my account to? All accounts upgraded
through Game Manager are automatically upgraded to the Standard plan, as indicated by the agreed-to base
rate listed within the Upgrade Account (1) flow.
To upgrade to a Premium plan, please contact PlayFab.
Title Launches
5/24/2022 • 2 minutes to read • Edit Online

Customers can upgrade their account plan and launch titles using the self-service upgrade and launch
experiences found in Game Manager.

Title Modes
A PlayFab title has two possible modes:
1. DEVELOPMENT MODE : A Development Mode title has no cost to the customer for the core services
(multiplayer server hosting, Party, and Insights are not core services, though they do have limited free usage
available in Development Mode - please see the individual feature pages for more information). Use
Development mode to experiment with most PlayFab offerings. A title in development mode is subject to the
specific player count and meter usage limits determined by PlayFab. For more information about included
limits, see development mode.
2. LIVE MODE : A Live Mode title is charged to the customer based on its tier of service. Any meter usage over
what is included in the account plan's base rate results in charges per meter consumed. For more
information, see Meters. Note that Live Mode should not be confused with a title being "live". A title may
have players using it even in Development Mode, though the title will be limited to the player account
maximum for Development Mode. Moving to Live Mode removes that limit.

Launching a title
WARNING
Launching a title is a permanent action. The title cannot return to Development mode after the launch is completed.

To be able to move a title from Development Mode to Live Mode, a title must be in a Studio with a paid account
plan.
Launching a Title within a Free Account Plan
Titles may only be changed to Live Mode in Studios owned by paid accounts. Follow the steps listed under
Upgrading from Free to a paid account to launch a title in conjunction with upgrading an account.
Launching a Title within a Paid Account Plan
To launch a title within a paid account plan:
1. Log in to PlayFab.com
2. Navigate to the My Studios page and identify the Development Mode title to be launched (2).
3. Select the down arrow on the title to open the drop-down menu (2).
4. From the drop down, select Launch Title .
5. If the title is linked to a free account plan, Launch Title takes you to the account upgrade flow described
in the Upgrading from Free to Standard section. If the title is linked to a paid account, continue to the
next step.
6. A pop-up will prompt you to confirm the title launch. Once Launch Title is selected, the launch is
complete and the title is no longer bound by Development Mode limits.
PlayFab Consumption: Best Practices
5/24/2022 • 24 minutes to read • Edit Online

With PlayFab's consumption-based pricing model, you only pay for the actual service usage of your titles. But
this raises an obvious question: how do you best optimize those titles to save money, while still implementing all
the features you need? In this document, we'll dive into those details, and talk about best practices that will help
you to plan ahead.
Before you move your titles from Development Mode to Live you can review the meter information in the Billing
Summary tab of the Game Manager. A good starting practice is to periodically confirm the meters by using a
separate title to check meter usage for real-world-player activity. You can have multiple titles in Development
Mode, so that you can create titles on the fly as you reach development stages where you want to checkpoint
that usage, and then delete those titles after you're done.
There are six consumption meters: Events, Profile, Content and Configuration, CloudScript, Insights, and
Multiplayer Services. The best way to begin optimizing a title is to look at each of the meters that it uses and see
how it accumulates over time. This allows you to quickly derive some obvious improvements. For more
information about meters, see Pricing Meters.

Events
There are two types of events in PlayFab: PlayStream and Telemetry.
PlayFab processes PlayStream events to check if they trigger PlayStream Actions you have defined, and to
update User Segmentation. Some PlayStream events are automatically generated as a result of calls to service
features such as authentication and statistic updates. Titles can generate their own custom events to extend this
functionality.
Telemetry events are not processed by PlayStream. These events are used for analytics, and they go straight to
the data warehouse. Telemetry events are not generated automatically in PlayFab; they are custom events
generated by the title.
For both event types, larger payloads of data increase the total amount of meter usage. You can reduce that
overall usage by making sure you're only sending the data you need. A rough guide is that any given event
increments the meter in question by 1 for every 1 KB of data in the event body.
To choose which event path best suits your usage, you should have a clear plan for how you intend to use each
custom event that you generate. Events that are only needed for offline evaluation of the title should go the
Telemetry route. This can help to significantly reduce cost, as the overage charge on Telemetry events are less
than half that of PlayStream.
If you're using one of the pre-built SDKs, it's important to remember that some analytics data on user behavior
is generated automatically as described in the PlayStream Event Model reference. To turn off optional events,
change the analytics setting in the Settings/Data Collection tab of your game in the PlayFab Game Manager.
Similarly, while it's a good idea to have the "generate PlayStream event" option turned on for your CloudScript
executions during debugging, you should make sure to disable that before going live. In the case of PlayStream
Action triggered CloudScripts, you can always turn them on later if you need to debug some behavior in the
wild.

Profile
The profile is effectively "everything about the player", including common elements such as inventory, saved
data, and statistics. It also contains the meta-information that you use to drive unique experiences through the
LiveOps capabilities in PlayStream, such as the User Segmentation mentioned above. In addition, some title-
level legacy features, such as Title Data, Catalogs, and Stores, are included in this meter, as their data
implementation is effectively the same as User Data. Since this set of meters is driven by all player actions, as
well as actions taken on players, it is overwhelmingly the one that needs the most optimization planning.
The primary contributing factors to the usage captured by the pricing meters is the amount of data that is read,
stored, and written, and how frequently you call the APIs that generate data that is metered.
For more information about the specific API calls that result in "spin" on these meters, see Pricing Meters.
We'll start with User Data and Statistics, since their usage patterns are similar, and then we'll talk about player
inventory management.
Data and Statistics
When evaluating your usage of User Data, the same approximation logic as for events applies–each 1 KB
increases the meter count by 1–though keep in mind that each "element" of a call should be thought of as
distinct for purposes of this calculation. Each key value pair in a call to update User Data is counted separately.
For reads, this 1 KB calculation applies to the total data returned, regardless of the number of key value pairs.
This means that writing 10 keys of 100 bytes each is 10 "ticks" of the profile write meter, since each key value
pair write is a minimum of 1 KB, while a read of those 10 keys is 1 "tick", since it's a total of 1 KB. For more
specific details on the usages, see Pricing meters.
Statistics are slightly more complex, as they also have an impact on leaderboards. As a general rule, you can
think of each statistic updated as incrementing the meter by 1, while reads are based on the total size of the data
read in each call. And since storage is priced per gigabyte (GB) and statistics typically consume only a few bytes
each, we'll focus on reads and writes.
Since the total data size is important, optimizing it is the first step. Fortunately, there are a wide range of well-
known techniques for this–using enums or IDs in place of spelled-out text for items, packing large data as
binary, or even using bitfields to pack data into smaller spaces. After that's done, the next step is to carefully
evaluate when you need to make those read and write calls.
If you're coming from PC or console development–especially single player games–this might be a new pattern.
But in those environments, you must be careful about resource hits and garbage collection on the client device
since those can cause degradation in performance at critical times. When your title uses resources that are in the
cloud, it's necessary to extend that logic to consider each resource hit as having a real cost, in addition to a
performance cost.
How do you determine the optimal frequency of reads and writes? Two of the most common concerns of
developers who want to update data and statistics more frequently are protecting against cheating, and having
timely information stored server-side either for player-to-player interactions or to prevent data loss if the game
exits unexpectedly.
Cheat Protection
While it might seem like you need to constantly update your backend data to ensure essential security, frequent
updates are rarely necessary if your game doesn't require fully server-authoritative control of the session. To
start, the fundamental question is how much security that you actually need.
For some games, particularly those that monetize primarily through in-game advertisements and don't have
leaderboards, cheating isn't much of a concern. In this case, trusting the data the client sends up is often a viable
approach, since the security of that data isn't really a concern. To identify cheating behaviors and decide how you
want to handle them, we recommend that you implement processes to review the events, data, and statistics of
your players.
For other games in which you need to support the integrity of competition or protect the overall player
experience, stronger security is more important. Depending on your specific requirements, certain approaches
can reduce the frequency of data reads and writes in those situations.
If your game is not real-time, one approach that we recommend is to aggregate information about the player's
game over some period of time–often a "round" of the game, taking several minutes–and then send that data to
a script that determines whether it is valid. The key elements to evaluate can be game-dependent, but some
examples of common concepts to consider are:
How long has it been since the last session report, and how long does the client say that it played in the
latest one?
What scores did the player register, and are they reasonable for that player given their level, equipment,
etc.?
For games with more real-time requirements, such as needing to update the server-authoritative player state
frequently, a better solution than frequent updates to the PlayFab-stored data is to use hosted game servers. In
that model, you connect the player to a server on session start. The server reads all the needed data from the
service for the player, and then host the simulation state for that player over time, with the client exchanging
data with the server at whatever rate you need. The server then updates the "long term storage" in PlayFab with
the latest data for the player, either at the end of a session, or every few minutes if your sessions are particularly
long.
This is the model used by real-time multiplayer games. It's also a valid technique for single-player titles that
require server-authoritative checks, though if that frequency is only a few times a minute per player, Azure
Functions CloudScript could be the better option. The total CloudScript cost is easy to compute. It's the total
gigabyte-seconds that you consume, with a minimum of 128 MB and 100 ms per execution, plus the normal
calculations for any other service API calls the script uses. For example, if you have a total memory footprint,
between your script code and variable usage in the script, of 250 MB, you would need to run that script for 4
seconds (across multiple users, most likely) to get to 1 GB/s. And within that script code, if you read or write
Entity Objects, Title Data, User Data, etc, you'll need to calculate the spin that each of those calls has on the
profile meters. Since hosted game server costs are dependent on how many servers you're running, and that in
turns depends upon how many players can be hosted on a server at a time, it's not necessarily trivial to
determine where the break-even point is between the two. But if you find that you need to call your scripts at a
high frequency, and need to read and write data from the service each time, it's very likely that a game server
solution is the better way to go.
Data Timeliness
One common theme we've heard among developers with high profile write rates is that they're concerned about
the player losing progress. If the player exits the game before it can save and the local state cannot be used the
next time the game is played, or that state needs to travel between devices, you want to have the PlayFab-stored
state information for the player be as up-to-date as possible.
For many games, you can address this issue by having a regular, infrequent heartbeat of updates to the service
(every fifteen minutes, for example). But including additional logic to lengthen or shorten that frequency can
also help. For example:
Include an "important update" override that causes an immediate write, and resets the timer, if the player
actively does something significant, so that it can't be lost.
If your game continues to progress with no player input, consider lengthening the heartbeat period if
there has been no input for a long time. This is especially important for idle games, where players
frequently leave them running overnight.
Give players a way to force an update directly, such as a button in a user menu. In this case though, be
sure to throttle the rate at which calls are actually made from the client device to PlayFab, so that a player
hitting that button over and over isn't generating a call each time.
If the client does have the state information the next time the game is played, you can compare the timestamp
locally to that of the data from the service and decide which to use, or even provide the player with the option to
choose.
A player's profile information may be relevant to more than just themselves. In some games, you might need it
to query cross-player, whether to spur competition or to directly influence the player experience through
asynchronous friend interactions, challenges, and so on.
For competition, Leaderboards are an ideal way to generate that tension by sharing a subset of information
about other players (often those close to the current player's score) via a single call to the service. Since it's
possible to return other profile elements, such as statistics and tags, using the Profile View Constraints, you can
present a rich set of information about these other players. But it's important to not iterate over the list of all
players in the leaderboard, trying to read additional information from each, as this would rapidly multiply the
total number of profile reads, driving up your costs.
For games that use cross-player data directly in the session, the most common optimization is to read only the
information about the few specific players with whom the local player is interacting. For real-time action games,
this is usually done on the server hosting the session. For others–such as games where players can attack each
others' bases–the most common approaches are to either read all that data onto the local device or to send the
local player only the subset of the other player's data that the local player should know. Games that do the
former use server-side logic to evaluate the final results the client sends. Games that do the latter update the
data iteratively over the course of the session with more data, when the local player should have access to it. But
even then, they also use server-side logic to evaluate the final results. Again, the tipping point in deciding
whether this should be done through script or on a hosted server is down to frequency. If it's more than a few
times a minute, you're better off using a hosted server for the portion of the session that requires that data.

Inventory
Inventory, and economy in general, requires a different approach. There's no avoiding the fact that if a player is
giving up something of real (money) or perceived (virtual currency or consumable containers) value, they have
an implicit expectation that the transaction will be honored. For any game with in-app purchases, an increment
to the profile meter for a purchase made by the player with real-world currency is a trivial cost. In many types of
games, inventory updates are infrequent enough to pose little concern for greatly increasing your overall usage.
But for those with more frequent inventory updates–even if you don't have in-game monetization–there are
optimization tricks to help reduce your costs.
A best practice is to only think of inventory in the literal sense, as reasonably finite inventory. For example, in an
incremental (or "idle") game, it can be tempting to think of each resource that the player acquires as an item,
incrementing the total number each time the player purchases another of it. But that model breaks down rapidly,
as you calculate the frequency with which players take those actions. Right away, you would have to deal with
each player hitting the meter hundreds or even thousands of times in a session. For situations like this, it's better
to think of those elements as User Data, and to update it to the service using the recommendations in the Profile
section above.
When it comes to games that have higher rates of update to inventory, we're back to the question of data
timeliness. For example, an action game might track on the number of bullets a player has, but the backend data
for that "stack" of bullets does not need to be updated with every pull of the trigger, especially if the game state
is managed in a hosted server. Stackables give you a performance and cost advantage, since you can represent
many virtual instances of an item as a single actual instance with a count. You can often aggregate changes to
stacks of items over time and update them at the end of a session, or periodically throughout the session. When
updating a stack, it's a good idea to call Player Item Management - Modify Item Uses to check whether you can
just change the count of the stack, rather than adding N instances of the item which must each be processed for
addition to the stack, then cleaned up.
By their nature, certain game genres, such as collectible card games, do need to update the player inventory at a
somewhat higher rate. But even here, there are still opportunities to aggregate inventory changes and reduce
the total usage on the profile meters. For example, in games that use drop tables, the design frequently employs
a container that has one or more "pulls" from each of several different drop tables. Typically, if these pulls are
only an occasional action the incremental cost is small enough to not cause concern. But if players can collect
many of those containers, and open multiples in a short period of time, you could provide an "open N" or even
"open all" option. In that case, you use PlayFab CloudScript using Azure Functions or your custom game server
to either query Player Item Management - Get Random Result Tables for the set of drop tables or call Player
Item Management - Evaluate Random Result Table without generating the inventory items. You could then
update the player inventory far more efficiently by only adding instances where needed, and then updating the
count of item stacks for the rest.

Content and Configuration


Where the Profile is primarily about the player, Content and Configuration is primarily about the title. A number
of title-level components, such as Push Notifications, email services, and Title News are all included in this meter.
In addition though, this is the meter used to track on Entity File usage. Similarly, requests for the URLs for
uploading and downloading CDN files are tracked on this meter, though it's important to clarify that CDN costs
are separate, and are billed based on the total gigabytes downloaded as described in Content Delivery Network
(CDN). The calculation of the Content and Configuration read and storage meters are similar to the Profile
meters in that they are based on the size of the data, though obviously the units are significantly larger than 1
KB. For the Content and Configuration write meter, it is solely based on the total number of write operations,
with each incrementing the meter by 1.
As a side note, the Entity File system is the recommended service for large data, whether it's associated with the
title, a Group, or an individual player. For games with large data saves per player, the Entity File system is
generally more cost effective; though do bear in mind that the frequency of those updates has an impact on
usage that is tracked. It's best to optimize the number of Files you need against the frequency with which they
need to be updated.
In terms of optimizing costs on the Content and Configuration meter, the most important thing to keep track of
is the frequency with which your title must request its own rarely changing configuration data. Primarily this is
Title Data, which is commonly used to manage aspects of your games that are the same across all users, such as
game balance/tuning data, achievement definitions, localization data, and so on.
For games that use CloudScript, if you find that there's a dependency on this title-level data for each call to a
script, you might want to consider "baking" that data directly into the script. You can do this by the simple
expedient of defining it as hard-coded data in the script itself, or by using static variables, as a means of caching,
to read the information from the service once per virtual machine (VM) instance. This way, the title-level data is
loaded the first time any given VM runs your script and is re-used by that VM on subsequent executions. Three
things to bear in mind here: first, the script is used by many different users, so nothing should be considered
consistent for an individual user between executions. Second, the processing of the data must be considered
stateless, since a single player could hit different machines for each call. And finally, you need to track on the age
of that data and periodically re-load it, to make sure you have the latest version.

CloudScript
This is one of the major "expansion joints" of the PlayFab service, allowing you to run server-authoritative logic
from a client device or a server, or even trigger it via PlayStream Rules (for example, when a player enters a
Segment). As opposed to custom game server hosting, you're only paying for the gigabyte seconds (GB/s) that
the script runs, with per-execution minimums of 128 MB and 100 ms. So if your script uses a total of 250 MB of
space (between script code and data), it would need to run a total of 4 seconds–likely across multiple
executions–to get to one GB/s.
Since the use cases for CloudScript generally revolve around taking actions on behalf of your players, we've
covered the majority of what you should be thinking about for optimizations in the last two sections on profile
and content/configuration meters. However, the total number of executions for a title is also tracked as part of
metering CloudScript usage, so it's valuable to review how often you need to make calls to CloudScript on a per-
player basis. For some games it might be significantly more cost efficient to use a hosted game server to have a
"hot" data store for active players, rather than try to manage a data store in iterative calls to CloudScript.

Insights
This meter is associated with all the analytics capabilities of the PlayFab service, from event ingestion and export
to Event History search and Data Explorer queries. Your usage here is influenced by how fast you need events
processed, how much event data that you want to keep hosted "hot" (for queries in the Game Manager), and
how much you use the service to evaluate your data, either through Data Explorer queries or visualization
software you connect to your data directly. This meter is impacted by both in-game activity (events) and out-of-
game activity (analytics).
Ultimately, this means that the costs on Insights are driven by how much event data you get from players and
how much analytics processing you do on that data. In terms of best practices, the advice on events above
applies to the former, while for the latter you can control your costs in two ways. First, and simplest, is that you
can set the total storage in the Insights Management tab of the Game Manager for your title to control how
much total event data you retain in PlayFab. Next, and in that same tab, you can set the performance level for
your title. This determines the total amount of CPU resources allocated to your title, as well as how much data is
stored "hot" for queries in the Event History. How much you need for each depends upon the needs of your data
analytics team members, so it's best to review this with them to understand what your settings should be.
For information about Insights and how to use it, see What is PlayFab Insights.
For information about Insight best practices, see Best Practices & FAQ.

Multiplayer Services
This one is the simplest of all, since the pricing is completely unchanged. In short, hosted Multiplayer Servers
and the Party service have always been charged on a usage basis.
For hosted game servers specifically, you can minimize your costs by optimizing the number of server cores you
have to have running at any given time to support as many players as possible.
If low ping times are important on those servers, you can choose which regions to run the servers. For most
games, the largest concentrations of players are limited to certain key regions, but if you have a widely
dispersed player population—particularly when you're in the long tail of your game—you'll need to weigh the
cost of running servers in every region near your players versus the impact of longer ping times on the subset
of players in areas with few players. One thing that can help with that is to make sure you're using our QOS
service to choose which regions to put players in, and then determine what your cut-off is for the minimum
number of players you need playing in a region for it to be viable.
To help get you through development without running up costs, we provide a significant number of free server
hours in our hosting service, and our Party service is free for all Development Mode titles. It's also worth calling
out that our Party service is also free for all use with Xbox Live signed-in players, and for titles in our Standard,
Premium, and Enterprise tiers, we provide a generous allowance of connectivity, voice, and Cognitive Services
(voice transcription and translation) at no additional cost, to help with 21st Century Communications and Video
Accessibility Act (CVAA) compliance.

Managing your Live Game


That covers the fundamentals of the meters, but what should you be thinking about once your title is live?
Managing your community of players primarily involves analytics (Insights, in the section above) and updates to
Content and Configuration. In addition, most games need to engage with players outside their normal
interactions with the game itself. From re-engagement campaigns (to entice players to come back), to
community rewards for meta-game activity, and even to thanking players for their own community work
outside the game, a common practice these days is to use LiveOps techniques to keep players highly engaged.
One key to this is making sure that you effectively target your segmentation to well-defined groups, not only to
keep costs down, but to make sure your logic is processed quickly. Take, for instance, player re-engagement–
getting players to come back after they've stopped playing for some period of time. A good way to approach
this is to define several lapsed user time frames, perhaps players who haven't played for 3, 7, and 21 days. For
each, you can take a different approach to re-engagement, starting with a simple "we miss you" message, and
culminating in a "here's some free gold/energy/etc." message (coupled, of course, with automatically adding that
to the player's account). For each of those, the recommended approach is to define a one-hour window based
on the last time the player signed in to play the game. That way, you're not only targeting the last time they
played, you're also keeping the set of players in the segment minimized, in order to make the operation as
efficient as possible. Using a Scheduled Task that fires once every hour on each of those segments, you send out
the messages and add any items or virtual currencies (VC) to the player inventories.

Summary
Ultimately, it's the features your game needs that determine its usage of a backend service like PlayFab. Really, it
all boils down to one comprehensive question: what requirements do you have for those features? Whether you
prioritize security, timeliness of data, level of player interaction/competition, or something else entirely, there are
any number of factors that can push you towards a higher level of interaction with backend data. Being able to
look at those requirements with a critical eye and discern which are hard needs and which are not, is very much
akin to optimization of any other code in your game. It's a matter of taking a careful look at where your resource
utilization is high and deciding whether you truly need it to be, or if there are ways you can redesign that logic
to reduce usage.
If the interaction is real-time, player-to-player, it's down to the complexity of that interaction. For most games of
this type, hosted servers that manage the simulation state and only update the backend data at the end of a
session (or every few minutes, if the sessions are long) are usually the best solution. But there are plenty of
cases where interaction is fully trusted, such as co-operative games, or those played only with (or against)
friends, minimizing the incentive to cheat. Still others have only minimal requirements for how the data for a
session must be checked, allowing both players to simply submit their reports after each session, so that server-
side checks can compare the two.
For any game without a real-time requirement, consider whether the player really needs up-to-the-second
accuracy. In highly competitive games with strong community interaction, that may very well be the case. But for
plenty of games, information that's a few minutes out of date doesn't impact the player experience.

Looking Ahead
As a service, PlayFab continues to evolve, and as it does we will continue to update our documentation to help
guide you through managing your costs while making use of the services that power the features you need. If
you have any suggestions or thoughts on how we can improve on this, feel free to reach out to our team via the
Contact Us form on our main site. For feedback on how to optimize a feature you have in mind, or for any
general technical questions on using PlayFab, you can contact our support team via the community forums or, if
you're in any paid tier of service, by submitting a ticket in the PlayFab Game Manager (click on the ? in the upper
right hand corner from any page of your title). Our partnership with our developer community provides us with
the feedback we need to keep growing and to stay ahead of your needs, so we're always happy to hear from
you!
Azure PlayFab roadmap
5/24/2022 • 4 minutes to read • Edit Online

Last Update: 23 March 2022


While Microsoft has a digital-only presence at Game Developer Conference (GDC) this year, our commitment to
serving the game development community is as strong as ever. The PlayFab team has put together some
exciting updates to share around our Multiplayer Services, Party, Experiments, Data Platform, and User
Generated Content (UGC) services. We have new demos, technical talks and documentation that will help you
dive deep into each update.
Make sure you visit our GDC Page and we highly recommend you follow our Microsoft Game Dev twitter handle
for the latest news on game development.
Before sharing our first roadmap update for 2022, this is a reminder that we welcome your feedback and would
love to hear from you. The Feature Requests section of our forum allows you to post, comment, and vote on
ideas from our community. Addressing issues also remains a high priority so continue to share your findings in
the Bugs section of our forums. Thank you for your continued support!
We love hearing from game creators that are using PlayFab for their current or in-development titles. If you see
something on this roadmap that is critical to your success or that you want more information on, let us know.
PlayFab Leadership is still hosting our series of ‘Outside-In’ sessions where we have customers come meet with
our team to help us understand your needs and goals. If you're interested in participating, reach out to us at:
PFOutsideInRequest@microsoft.com

What’s new
Data Connections (formally Bring Your Own Storage): We're introducing the ability to write
PlayStream and telemetry events to your own storage account. With the ability to export data from PlayFab
to your own data storage of choice, you'll be able to take advantage of Azure services and have full control
over your data in terms of access, scale, latency, retention and privacy. This feature enters Public Preview this
week. To read more about the release, see Take control of data in your resources using Data Connections
blog post.
Matchmaking: We're adding real time notifications to avoid polling the ticket status and integration with a
new Lobby feature. The updated client SDK for Matchmaking with real-time notifications is now available
to ever yone in public preview . To learn more, see Matchmaking documentation and download the SDK
today to try it out. Remember to check out our new ID@Azure program. Sign up benefits includes the use of
this new matchmaking service at no cost for most games. To learn more, see Introducing ID@Azure: Your
Journey in the Cloud Starts Today blog post.
Lobby: A new feature that allows for temporary grouping of players for orchestrating multiplayer
experiences, including searching for available lobbies to join. It includes member properties, as well as lobby
and search properties to use for gameplay coordination. The new Lobby service with real-time notifications
is now available to ever yone in public preview . To learn more, see Lobby documentation. Remember to
check out our new ID@Azure program. Sign up benefits includes the use of this new Lobby service at no cost
for most games. To learn more, see Introducing ID@Azure: Your Journey in the Cloud Starts Today blog post.
UGC General Availability (GA): We've moved UGC out of public preview and into full release (GA). In
addition to various API tweaks and bug fixes, we’ve added Game Manager improvements and features to
help developers better manage their User Generated Content catalog. To learn more, see Growing
marketplace engagement with Azure PlayFab UGC GDC video and PlayFab User Generated Content
documentation.

What's on-deck
Leaderboards v2: Leaderboards v2 remains in private preview for now.
Economy V2 Public Preview coming in third quar ter of 2022! Player inventories and wallets, receipt
validation on the most popular marketplaces, bundles, stores, currencies, and more.
Segmentation: We'll be introducing a new API called Expor tPlayersInSegment into a beta release as an
enhancement to the existing GetPlayersInSegment API. Also, we'll be making it easier to define segments
comprising a fixed list of players.

What's been released (since our last update in October)


CloudScript Functions is now fully available on Azure: The new and improved CloudScript Functions
is now fully available and fully on Azure. To learn more, see Cloudscript Using Azure Functions blog post and
Getting Started.
Event Sampling Private Preview: Late last year we released Event Sampling into private preview. It allows
for more granular control over both your PlayStream events and Data Ingestion. To learn more, see
Managing Your Events with Event Sampling blog post and Manage Events quickstart.
Unreal GSDK Plugin: We have a new GSDK plugin that makes it easier to upload your Unreal build to
Multiplayer Servers (MPS). To learn more, see New Unreal GSDK Plugin simplifies Azure MPS deployment
blog post and Getting started.
New How-to: We published a new article on how to attach a profiler and debug your MPS Game Servers.
To get started, see Attach a profiler.
Auto Crash Dumps: We’ve added the ability to enable automatic crash dumps on Windows container-
based MPS Game Servers. For documentation, see Crash Dump Collection.
UGC SDK: In November we released the updated SDK that supports our Azure PlayFab UGC Public Preview.
You can read more about this new set of services and learn how to jumpstart a creator community within
your game. For the blog post announcement, see Announcing Azure PlayFab User Generated Content (Public
Preview). Finally, if your game is running on GameSparks and you’re looking for an alternative solution, our
services are ready to use, regardless of what engine, platform, or store you currently have integrated with. If
you are struggling with the path forward, our partners Alice and Smith and GameCloud are available to help
you migrate. For more information, see GameSparks to Azure PlayFab Migration. To connect with us, find us
on Discord Server #migrate-to-playfab.
Thank you to all our amazing game creators building with PlayFab today. None of this would be possible
without you. Keep the feedback coming!
PlayFab Release Notes 2022
5/24/2022 • 2 minutes to read • Edit Online

NOTE
For release notes about service releases and product updates, see the release notes section on PlayFab's public GitHub
repository

220509
Date: 2022-05-09
Supports the February 8 2022 PlayFab service release
Minor bug fixes

220214
Date: 2022-02-14
Supports the February 8 2022 PlayFab service release
Minor bug fixes

220131
Date: 2022-01-31
Supports the November 17 2021 PlayFab service release
Minor bug fixes

220118
Date: 2022-01-18
Supports the November 17 2021 PlayFab service release
PlayFab Release Notes 2021
5/24/2022 • 2 minutes to read • Edit Online

NOTE
For release notes about service releases and product updates, see the release notes section on PlayFab's public GitHub
repository

211108
Date: 2021-11-08
Supports the October 21 2021 PlayFab service release

211012
Date: 2021-10-12
Supports the August 24 2021 PlayFab service release

210927
Date: 2021-09-27
Supports the August 24 2021 PlayFab service release
Updated Postman collection format to V2

210913
Date: 2021-09-13
Supports the August 24 2021 PlayFab service release
Adds bug fixes to UnrealMarketplacePlugin

210830
Date: 2021-08-30
Supports the August 24 2021 PlayFab service release

210816
Date: 2021-08-16
Supports the July 21 2021 PlayFab service release
Adds bug fixes to UnitySDK

210802
Date: 2021-08-02
Supports the July 21 2021 PlayFab service release

210628
Date: 2021-06-28
Supports the June 9 2021 PlayFab service release

210521
Date: 2021-05-21
Supports the April 28 2021 PlayFab service release

210427
Date: 2021-04-27
Supports the March 31 2021 PlayFab service release

210406
Date: 2021-04-06
Supports the March 31 2021 PlayFab service release

210315
Date: 2021-03-15
Supports the March 8 2021 PlayFab service release

210208
Date: 2021-02-08
Supports the February 3 2021 PlayFab service release

210125
Date: 2021-01-25
Supports the January 20 2021 PlayFab service release

210111
Date: 2021-01-11
Supports the January 2021 PlayFab service release
PlayFab Release Notes 2020
5/24/2022 • 6 minutes to read • Edit Online

NOTE
For release notes about service releases and product updates, see the release notes section on PlayFab's public GitHub
repository

201218
Date: 2020-12-18
Minor bug fixes

201207
Date: 2020-12-07
Supports the December 2nd PlayFab service release
UnrealMarketplacePlugin specific changes
Fixed static settings issues. Please follow the new upgrade guide.

201119
Date: 2020-11-19
PostmanCollection specific changes
Added an auto-login for Title Entity, when appropriate
UnitySDK specific changes
Fixed a spammy log for Unity 2020
Unity 2020 fully supported now
XPlat C++ SDK specific changes
Fixed QoS search response when all servers time-out.

201027
Date: 2020-10-27
Supports the September 2nd PlayFab service release
Minor updates were made to APIs.

201014
Date: 2020-10-14
Supports the September 2nd PlayFab service release
(Also supports new methods in the Experimentation API which will appear in a near-future Service release)
PlayFab is committed to enable you to use our services for developing cross-platform and cross-device games
using various game engines and frameworks. To help us better focus on creating new features that you need, we
are opening the following SDKs for community contributions. If you have more questions or need support, go to
PlayFab community forum. This will be our last official update to the following SDKs:
https://github.com/PlayFab/Cocos2d-xSDK
https://github.com/PlayFab/Objective_C_SDK
https://github.com/PlayFab/PhpSdk
https://github.com/PlayFab/PythonSdk

200914
Date: 2020-09-14
Supports the September 2nd PlayFab service release

200901
Date: 2020-09-01
Supports the August 26th PlayFab service release

200817
Date: 2020-08-17
Supports the August 12th PlayFab service release

200805
Date: 2020-08-05
Supports the August 5 PlayFab service release

200730
Date: 2020-07-30
Supports the July 15 PlayFab service release

200713
Date: 2020-07-13
Supports the July 1 PlayFab service release

200615
Date: 2020-06-15
Supports the June 10 PlayFab service release

200602
Date: 2020-06-02
Supports the May 27 PlayFab service release
200518
Date: 2020-05-18
Supports the May 13 PlayFab service release
UnitySDK specific changes:
PlayFab SDK no longer sets Application.runInBackground = true
Game Developers are responsible for verifying API calls during app focus change or before shutdown,
are successful
XPlat C++ SDK specific changes
In the CURL HTTP implementation, more CURL error states are monitored and processed
The Event Pipeline feature now uses and supports the background thread feature
When TitleId is not set, API methods now throw real-time exceptions synchronously, rather than reporting
the issue in synchronous or threaded callbacks

200422
Date: 2020-04-22
NodeSDK Update:
Hotfix
Fixed an issue where recent NPM packages were missing a critical file, and could not be imported
Fixed an issue where some type definitions were incorrectly set to "Number" rather than proper types

200421
Date: 2020-04-21
SDK's support the PlayFab Service as of 2020-04-21. Service release notes available here

200402
Date: 2020-04-02
API Changes
Insights:
Please see our new Insights feature!

200330
Date: 2020-03-30
API Changes
Authentication:
Added new LoginIdentityProviders for Apple and Nintendo
Multiplayer Server:
Added new BuildRegion management functions DeleteBuildRegion and UpdateBuildRegion
UnrealMarketplacePlugin:
Added new Mac build helper scripts
XPlat C++ SDK specific changes
Fixed some threading issues for the PlayFabEventPipeline
UnrealMarketPlacePlugin specific changes
Security bug fixes

200303
Date: 2020-03-03
API Changes:
server.UnlinkXboxAccountRequest no longer requires the XboxToken to be unlinked
The Experiments feature and API have been released
See our Blog Post for more details
New Methods
client.LoginWithApple
client.LinkApple
client.UnlinkApple

200220
Date: 2020-02-20
New
Automation - We released a new Visual Studio Code extension for PlayFab. You can find the source code in
Github.
Cpp Gsdk- Breaking change
Due to thread safety concerns, the signatures of the following methods were modified:

M ET H O D N A M E O L D RET URN T Y P E N EW RET URN T Y P E

GSDK::getConfigSettings() const std::unordered_map const std::unordered_map


<std::string, std::string>& <std::string, std::string>

GSDK::getLogsDirectory() const std::string& const std::string

GSDK::getSharedContentDirectory() const std::string& const std::string

Please see our Upgrade guide

200218
Date: 2020-02-18
API & Documentation Changes:
New api methods:
admin.CreateInsightsScheduledScalingTask
multiplayer.GetMultiplayerSessionLogsBySessionId
New feature and methods:
A new mechanism for Cloud Script: Azure functions, can now be used in PlayFab
Feature Documentation
List of New Methods:
cloudscript.ExecuteFunction
cloudscript.ListFunctions
cloudscript.ListHttpFunctions
cloudscript.ListQueuedFunctions
cloudscript.PostFunctionResultForEntityTriggeredAction
cloudscript.PostFunctionResultForFunctionExecution
cloudscript.PostFunctionResultForScheduledTask
cloudscript.RegisterHttpFunction
cloudscript.RegisterQueuedFunction
cloudscript.UnregisterFunction
Api method changes:
Region request parameter is no longer required for multiplayer.GetMultiplayerServerLogs
CSharpSdk specific changes:
Overhaul and improve the QoS ping calculation for PlayFab Multiplayer

200213
Date: 2020-02-13
PlayFab's Multiplayer Servers introduces an auto scaling enhancement named Dynamic Standby that monitors
standby server threshold levels and dynamically activates increased provisioning of game servers so that
demand can be met at scale. This feature feature adds a new object to the Multiplayer programming interface
called "DynamicStandby" object. The Dynamic Standby object is an optional property of the BuildRegionParams
object.
Dynamic Standby is an advanced game server feature and editing the settings from its default values should be
done with caution. Configuring Dynamic Standby can be accomplished in the Game Manager Developers' portal
or programmatically editing properties of the Dynamic Standby object. To learn more about Dynamic Standby,
visit its user guide in the PlayFab Multiplayer Servers online documentation.

200128
Date: 2020-01-28
Multiplayer Server Event Changes:
We are introducing a change to the Multiplayer Server event naming convention in efforts to unify our event
names with that of the rest of PlayFab event names. Additionally, we are making these changes in advance of the
Multiplayer Server feature becoming Public Preview. The changes are:
Multiplayer Server event names will be updated to use PascalCasing
Multiplayer Server events will no longer be sent in the legacy v1 PlayStream event format; only v2
PlayStream event format will be supported
These two changes represent breaking changes, particularly for developers who take a dependency on non-
right casing of names or PlayStream v1 of Multiplayer Server events. These changes are not breaking for
developers who leverage event names in the Game Manager UI (cloud script, insights, rules, or scheduled tasks).
This change will take effect Wednesday February 26, 2020 at 10:00 AM PST. Please adjust your code for these
changes before the change date.
Format Changes
Generally, PlayFab Events have the format similar to:
{
'Event Name':'my_event'
'Payload':
{
'prop1':1
'prop2':2
'camelcase':3
}
}

The fundamental format change are that properties in the events Payload object will be updated to use
PascalCasing for consistency with other PlayStream events. Therefore, the new property names will meet the
following format:

{
'Event Name':'my_event'
'Payload':
{
'Prop1':1
'Prop2':2
'CamelCase':3
}
}

Observe that the property names of Multiplayer server events are now updated to use PascalCasing.
This change will impact customers who process Multiplayer server events in (a) Kusto queries or (b) PlayFab
cloud scripts. Lastly, if a customer leverages the PlayFab Event Archive feature (currently in public preview), the
properties of Multiplayer server events exported will also be formatted in PascalCasing.
Schema Changes
The second change introduced are that Multiplayer server events will only be delivered in PlayStream v2 format
and no longer the legacy PlayStream v1 format.
PlayFab currently supports two event schemas.

M ULT IP L AY ER EVEN T S N A M ESPA C E


SC H EM A F O RM AT DESC RIP T IO N VA L UE

PlayStream V1 Designed around player events com.playfab.events.multiplayer

PlayStream V2 Designed around entity events playfab.servers

Generally, PlayFab API's generate events in either PlayStream V1 format or PlayStream V2 format. For example,
APIs that grant player items generated a PlayStream V1 event. Whereas APIs that grant entity items generated a
PlayStream V2 event.
Because the Multiplayer Servers launched in public preview at or near the same time PlayStream V2 was
introduced, the Multiplayer Server feature supported both PlayStream V1 and V2 formats. Meaning, every
Multiplayer Server API call generated two events; one in V1 and V2 format.
To remove duplication, Multiplayer server events in the 'com.playfab.events.multiplayer.servers' namespace are
being deprecated. Events in the 'playfab.servers' namespace will be continue to be supported.
To distinguish between Multiplayer Server events of V1 and V2 format, examine the namespace property of the
event. The namespace is specified in the 3rd column of the table above. The JSON representation resembles the
following:
{
'FullName':
{
'Namespace':'abc',
'Name':'xyz'
}
}

The property to search for is named Namespace .

200121
Date: 2020-01-21
API & Documentation Changes:
PlayFab API Documentation site has been fully migrated to https://docs.microsoft.com/gaming/playfab/
Most api.playfab.com links have been converted to their equivalent docs.microsoft.com links
Most original links redirect to the new site properly
Let us know in the forums if any old links don't work
New api methods:
multiplayer.ListServerBackfillTicketsForPlayer
multiplayer.GetServerBackfillTicket
multiplayer.CreateServerBackfillTicket
multiplayer.CancelServerBackfillTicket
multiplayer.CancelAllServerBackfillTicketsForPlayer
server.UnlinkPSNAccount
server.LinkPSNAccount
LuaSdk specific changes:
Minor login bugfix
PhpSdk specific changes:
Minor syntax fix for strict correctness
UnitySDK specific changes:
Update the GitHub repro and project structure.
Moving the Unity EdEx package from (UnityEditorExtensions)
[https://github.com/PlayFab/UnityEditorExtensions] to (UnitySdk)
[https://github.com/PlayFab/UnitySDK/blob/master/Packages/PlayFabEditorExtensions.unitypackage]
In the future, we will also be phasing out the separate UnityEditorExtensions repo
PlayFab Release Notes 2019
5/24/2022 • 5 minutes to read • Edit Online

191218
Last SDK publish of 2019!
API Changes:
New methods: GetMultiplayerServerLogs and UntagContainerImage
Many minor bug fixes across most SDKs including: ActionScriptSdk, CloudScript, CSharpSdk, UnitySDK,
UnrealSDK
NodeSDK specific changes:
[Minor breaking change] Error situations now throw error() objects instead of plain strings
UnitySDK specific changes:
Created asmdef files for Unity to de-couple PlayFab from the Unity runtime DLL
Verified working on Unity: 5.6.Latest, and all versions from 2017.1.Latest to 2019.3.Latest
UnrealSDK specific changes:
Added support for Unreal 4.24
Verified working on 4.22, 4.23, 4.24
XplatCppSdk specific changes:
This release has minor breaking changes, that will require some code changes in your project
Please see our upgrade guide
(Breaking change - All Customers) Some PlayFabSettings variables have been moved
Requires minor code changes for all customers. Please see our upgrade guide
Major fixes to instance-API data isolation, which includes some signature and usage changes
Requires customer code changes if you used instance-API's,
C++ syntax improvements (for const correctness and pointer vs references)
Minimal chance of customer code adjustments
Major fixes to timestamps on all platforms
Requires customer code changes if you read or write timestamps in the PlayFab API, models, or
PlayFab timestamp utility methods
Most customers will only observe timestamps will be correct and threadsafe on all platforms now
Minor project updates and resolved warnings for most platform-specific projects/solutions

191122
Date: 2019-11-22
CSharpSdk specific hotfixes:
Fixed an issue where request authentication wasn't always applied properly when making API calls
Fixed some warnings
API calls from the main GUI thread will stutter the program (because this is an anti-pattern), but will no
longer deadlock the program
191121
Date: 2019-11-21
API Changes:
Error code documentation for many methods have been updated
CSharpSdk specific changes:
Removed hard coded references to SimpleJson, the default Json Serializer.
This will fix some issues when customers replace the default serializer with their own.
NodeSDK specific changes:
Minor updates to typescript definitions
Several locations that used to throw strings, now throw proper Errors
Phaser 3 compatibility fix
UnitySDK specific changes:
Removed hard coded references to SimpleJson, the default Json Serializer.
This will fix some issues when customers replace the default serializer with their own.
Verified working on Unity: 5.6.Latest, and all versions from 2017.1.Latest to 2019.2.Latest
UnrealSDK specific changes:
Verified working on 4.21, 4.22, 4.23
XplatCppSdk publish delayed:
We have some significant improvements and changing coming soon, but they're not finished. Consequently,
XPlat could not be published this release.
There will be new features, performance and signature improvements.
There will be very minor breaking changes, and an upgrade guide.
Stay tuned for next release!

191029
Date: 2019-10-29
API Changes:
TreatmentAssignment used in the client "Login With ..." method calls.
Minor bug fixes in XplatCppSdk
Minor PythonSDK bug fix
Some NodeSDK issues have been resolved
UnrealSDK specific changes:
Minor issue fix regarding required member variables in request containers
Verified working on 4.21, 4.22, 4.23
UnitySDK specific changes:
Verified working on Unity: 5.6.Latest, and all versions from 2017.1.Latest to 2019.2.Latest

191015
Date: 2019-10-15
API Changes:
Minor bug fixes in the XplatCppSdk- PlayFab enums should now be enum classes, therefore strict typing will
start to be enforced on PlayFab enums (see opensource cppCoreGuidelines on enum classes)
Profiles now have ExperimentVariants (PlayerProfiles and ProfilesAPI with updates to Admin and Server
API's)
Updating Client error messages for AccountNotFound
Events API added clarifying descriptions to what namespaces are allowed for custom PlayStream events
MultiplayerAPI added Aliases with CreateBuildAlias, DeleteBuildAlias, GetBuildAlias, UpdateBuildAlias
UnrealSDK specific changes:
Verified working on 4.21, 4.22, 4.23
UnitySDK specific changes:
Verified working on Unity: 5.6.Latest, and all versions from 2017.1.Latest to 2019.2.Latest

191001
Date: 2019-10-01
API Changes:
Minor bug fixes with Unity, we should no longer see benign errors when upgrading the SDK
Minor bug fixes with C++, nuget package should no longer require additional work to get lib_json working
Minor documentation description updates
UnrealSDK specific changes:
Verified working on 4.21, 4.22, 4.23
UnitySDK specific changes:
Verified working on Unity: 5.6.Latest, and all versions from 2017.1.Latest to 2019.2.Latest

190916
Date: 2019-09-16
API Changes:
Error code updates
UnrealSDK specific changes:
Minor build warning fixes
Updated for 4.23 compatibility
Verified working on 4.21, 4.22, 4.23
UnitySDK specific changes:
Verified working on Unity: 5.6.Latest, and all versions from 2017.1.Latest to 2019.1.Latest

190903
Date: 2019-09-03
API Changes:
Added GetStoreItems to the Server API
Various minor syntax bug fixes
UnrealSDK specific changes:
Verified working on 4.20, 4.21, 4.22
UnitySDK specific changes:
Verified working on Unity: 5.6.Latest, and all versions from 2017.1.Latest to 2019.1.Latest

190821
Date: 2019-08-21
API Changes:
[Authentication API]https://docs.microsoft.com/rest/api/playfab/authentication/authentication?) has a new
LoginIdentityProvider
Add CatalogVersion param to receipt validation APIs
PurchaseReceiptFulfillment - Receipt validation APIs return fulfilled items example Restore IOS Purchases
UnrealSDK specific changes:
Verified working on 4.20, 4.21, 4.22
UnitySDK specific changes:
Verified working on Unity: 5.6.Latest, and all versions from 2017.1.Latest to 2019.1.Latest

190717
Date: 2019-07-17
API Changes:
WriteTelemetry is now out of Beta as a public API
Multiplayer APIs have moved out of Beta to CSharpOnly
Minor API Error Code updates
UnrealSDK specific changes:
Verified working on 4.20, 4.21, 4.22
UnitySDK specific changes:
Verified working on Unity 5.6.Latest, and all versions from 2017.1.Latest to 2019.1.Latest

190625
Date: 2019-06-25
API Changes:
minor API changes
Authentication bug fixes
UnrealSDK specific changes:
Verified working on 4.20, 4.21, 4.22
UnitySDK specific changes:
Verified working on Unity 5.6.Latest, and all versions from 2017.1.Latest to 2019.1.Latest

190610
Date: 2019-06-10
API Changes:
Minor bug fixes
Authentication API Changes:
EntityLineage
ValidateEntityToken

190520
API Changes:
Minor bugfixes
UnrealSDK specific changes:
Verified working on 4.20, 4.21, 4.22
UnitySDK specific changes:
Verified working on Unity 5.6.Latest, and all versions from 2017.1.Latest to 2019.1.Latest

190509
Date: 2019-05-09
API Changes:
New Methods
multiplayer.GetTitleMultiplayerServersQuotas
server.AddGenericID
server.GetPlayFabIDsFromGenericIDs
server.LinkServerCustomId
server.RemoveGenericID
server.UnlinkServerCustomId
New Push Template Methods
The three new APIs for Push Notifications enable developers to Delete, Create, Save, and Send Push
Notification Templates
server.DeletePushNotificationTemplate
server.SavePushNotificationTemplate
server.SendPushNotificationFromTemplate
UnitySdk specific changes:
Verified working on 2019.1
CSharpSdk and XPlatCppSdk specific changes:
Minor bugfixes

190424
Date: 2019-04-24
API Changes:
]
Updated Error codes for the following APIs in the PlayFab API: Admin , Authentication , CloudScript ,
Groups , Matchmaker , and Multiplayer .

190410
Date: 2019-04-10
Profiles API Changes:
EntityStatisticValue
EntityStatisticChildValue

190312
Date: 2019-03-12
API Changes:
New [Multiplayer]https://docs.microsoft.com/rest/api/playfab/multiplayer/multiplayerserver?) APIs

190304
Date: 2019-03-04
API Changes:
Windows C++ SDK is now deprecated. We recommend using the XPlatCppSdk for any windows C++
development

190219
Date: 2019-02-19
Minor bug fixes

190205
Date: 2019-02-05
API Changes:
Updated obsolete documentation meta data
Added TypeString as an Alternate name for Type in most APIs
Added AddLocalizedNews to the Admin API
Added GetPlayFabIDsFromPSNAccountIDs to the Server API

190123
Date: 2019-01-23
API Changes:
Added another MatchmakingEntityInvalid reason - NoLeaderboardForStatistic
Added CurrentSer verStats to Multiplayer Models
Various bug fixes across Unity
Xbox xplat nugets are also available: https://www.nuget.org/packages/com.playfab.xplatxboxsdk.v141/
PlayFab Release Notes 2018
5/24/2022 • 8 minutes to read • Edit Online

181218
Date: 2018-12-18
XPlatCppSdk specific changes
XPlatCppSdk -SDK Breaking Change : Updated the folder structure for the XPlatCppSdk repo. If you are
using the SDK with project references, an update to vcxproj files path would be required.
Adding Xbox support to the XPlatCppSdk . Refer to the C++ quickstart for Xbox.
New API
Added PlayFabEventApi to support Heavyweight (low throughput) and Lightweight (high throughput)
custom events.
UnrealMarketplacePlugin specific changes
UnrealMarketplacePlugin
Adding support for Unreal Engine 4.21

181204
Date: 2018-12-04
XPlatCppSDK specific changes
XPlatCppSDK
Added support to build external dependencies.
Updated nuget composition. This is not a breaking change. Added binaries for the external
dependencies to the nuget and updated the properties sheet.
Bug fixes for QoSAPI .
CSharpSDK specific changes
CSharpSDK
Added .NET Standard 1.1/2.0 (plus .Net Core) support.
Updated nuget composition. The package now contains binaries for .Net Standard 1.1/2.0 and
portables also.
Migrated VS project files to VS 2017 standard.
UnitySDK specific changes
UnitySDK
SDK Breaking Change : The SimpleGet success callback signature has changed, and now must
accept a new single parameter of a byte[].
Added SimplePost .

181105
Date: 2018-11-05
API changes
PlayFab now supports login and account-linking with OpenID .
Additional XboxLive ID support, and enabling Xbox login via server.
In preparation for wider release of the service, we are rolling out PlayFab Multiplayer Servers 2.0 APIs. See
PlayFab Multiplayer Servers 2.0 (Thunderhead) for more information

181001
Date: 2018-10-01
API changes
A variety of deprecations have taken effect, and those elements have been removed from SDKs and
documentation.
Some Admin API methods related to unreleased features have been hidden.
server.DeleteUsers deprecation has taken effect.
A field deprecation for ServerHostname , spread across a variety of matchmaking related calls in admin,
client, matchmaker, and server APIs has taken effect. ServerIPV4Address is the replacement.
UnitySDK changes
Minor fixes/improvements to ScreenTime analytics.
All SDKs
The automated-build branch structure for GitHub repos is changing.
The normal customer facing branches, "versioned" and "master" will be unchanged.

180924
Date: 2018-09-24
API changes
Adding Metadata to the DeleteMasterPlayerAccountRequest Model.
Bug fixes in the Unreal Marketplace Plugin to expand supported versions.

180917
Date: 2018-09-17
API changes
The Server API method DeleteUsers is deprecated, and replaced with DeletePlayer
Unreal Marketplace Plugin:
Updated Marketplace Plugin to include our Blueprint interface.
New Unreal Engine quickstart guide
View in Unreal Marketplace

180906
Date: 2018-09-06
New API
Localization
New PlayStream event documentation
client_focus_change
client_session_start
player_device_info

180829
Date: 2018-08-29
API changes
renaming Entity.TypeString to Entity.Type .
renaming EmptyResult to [EmptyResponse].(
xref:titleid.playfabapi.com.groups.groups.removemembers#emptyresponse )
Renamed most Authentication function calls like GameServer to MutliplayerServer .
Admin.GetUserAccountInfo has more detailed platform information.
Objective C specific changes
Various bug fixes and refactors.
Changing AttributeInstallRequest to be API-specific.
Unreal Engine specific changes
Adding in UE marketplace plugin to SDK generator.

180809
Date: 2018-08-09
API group changes
We have separated the Entity API Group into multiple new API Groups.
This is a big SDK breaking change for anybody using the former Entity API.
See our Upgrade Guide!
(Please note, the links for blog and upgrade guide may not work yet, they're almost done.)
API changes
New API Methods:
The following APIs are released and visible in SDK, but the accompanying documentation isn't ready
yet:
client.LoginWithNintendoSwitchDeviceId
client.UnlinkNintendoSwitchDeviceId
server.GetPlayFabIDsFromNintendoSwitchDeviceIds
client.LoginWithFacebookInstantGamesId (not ready to use yet)
client.UnlinkFacebookInstantGamesId (not ready to use yet)
server.GetPlayFabIDsFromFacebookInstantGamesIds (not ready to use yet).
New PlayStream Events
title_hopper_config_updated event renamed to title_queue_config_updated
General changes
The parameter ServerAddress in many models has been deprecated in favor of the new
ServerIPV4Address .

Unreal (multiple SDKs) Specific Changes


Minor updates to both SDKs/plugins leading to a final merge to the Marketplace plugin. (Coming soon!)
PythonSDK! specific changes
PythonSDK!
Bug fixes and improvements.
Bug fixes and improvements.
UnitySDK and CSharpSDK specific changes
UnitySDK and CSharpSDK
Added a new structure called Plugin Manager. For now, this is just a foundation for future changes.
Some old function signatures have been marked as obsolete, and should be updated. (No breaking
changes though).
Found and resolved multiple issues with HTTPS.Put, which makes Entity Files more accessible on more
platforms.
Bug fixes in the ScreenTime feature.

180716
Date: 2018-07-16
UnitySDK changes
UnitySDK
Fixed minor issues with ScreenTime under some rare circumstances.
CSharpSDK changes
CSharpSDK
Added Plugin Manager API to C# SDK, to support optional custom implementations of JSON
Serializer and HTTP client.
UnrealCppSdk Changes: (UPDATED : This SDK has been deprecated. For the new unreal SDK,
please refer to UnrealMarketplaceSDK)
Unreal 4 C++ SDK is also published on Unreal Marketplace!

180710
Date: 2018-07-10
Unity hotfix release
Further refinements and optimizations to the ScreenTime events.

180709
Date: 2018-07-09
Hotfix release
Fixing some minor issues with last week's deployments.
Everything in last week's release notes should now actually work as promised.

180706
Date: 2018-07-06
API changes
New API Method:
entity.WriteEvents
UnitySdDK specific changes
UnitySdDK
Screen time tracking, described in the previous release is no longer Beta-only.
180705
Date: 2018-07-05
API changes
EntityAPI.ExecuteEntityCloudScript
PlayStreamEventModel.title_hopper_config_updated

New PythonSDK! changes


PythonSDK!
tested with 2.7
UnitySDK changes
UnitySDK
Wrapped some utilities in a namespace to avoid 3rd party conflicts.
Editor Extensions should misbehave less, and display fewer warnings.
New Feature - read our Sessions tutorial.
JavaScriptSDK changes
JavaScriptSDK
customData relay parameter should now work for Login functions.

XPlatCppSDK specific changes


XPlatCppSDK
Large results will now be parsed correctly.

180618
Date: 2018-06-18
API changes
Added new error codes in a variety of API methods.
Multiple entity-related PlayStream events now describe their EntityLineage.

180528
Date: 2018-05-28
API changes
New API Methods:
Admin.GetPlayedTitleList
Admin.DeleteMasterPlayerAccount
Admin.ExportMasterPlayerData
This is a part of the new GDPR launch. See our blog here
Updated Error codes in a variety of API methods
New PlayStream Event:
player_data_exported

180514
Date: 2018-05-14
XPlatCppSDK specific changes
XPlatCppSDK
Fixes in JSON serialization.

180507
Date: 2018-05-07
API changes
New API Method:
entity.GetProfiles
New PlayStream Events:
entity_executed_cloud_script
Updated API Method:
client.RegisterPlayFabUser now returns result.EntityToken
UnitySDK specific changes
UnitySDK
HttpWebRequest certificate validation security has been improved.
No longer default to ignoring all certificates.
Customers are expected to implement their own certificate validation, or call
PlayFab.Internal.PlayFabWebRequest.SkipCertificateValidation() .

WindowsSdk specific changes


Fixed hundreds of Level 4 warnings.
The version number published in PlayFabSettings.cpp has been corrected.
Most previous versions will have all had the wrong version number embedded in-code, and in call headers.
XPlatCppSDK has been created
XPlatCppSDK
Currently in beta.
Built using Windows SDK as a template.
May become a replacement to Windows SDK (At least several months away).
Upgrade should require almost no breaking changes.
Some cpprestsdk strings should be converted to std::string .
Some web::json::value types have been converted to json::value .
timestamps are not fully tested in Linux.
NuGet package
Uses lighter weight dependencies
Specifically jsoncpp and curl, rather than cpprestsdk .
Uses std::string everywhere, rather than a mix of 2 string types.
Adds Linux Support.

180414
Date: 2018-04-14
UnrealCppSdk HotFix: (UPDATED : This SDK has been deprecated. For the new unreal SDK, please refer to
UnrealMarketplaceSDK)
Issues were discovered in the Entity API release for UnrealCppSdk. These are hot fixed, and the Entity API
should now work as expected.
180409
Date: 2018-04-09
API changes
HotFix:
Only the date was updated, not the major/minor version numbers.
Guilds:
client.GetAccountInfo.UserAccountInfo.UserTitleInfo.TitlePlayerAccount now contains the required
information to identify other players and add them to your guild/group.
The same information can also be found with admin.GetUserAccountInfo and
server.GetUserAccountInfo.
UnitySDK specific changes
UnitySDK
Performance improvement for default HTTP settings (UnityWWW), for long-running processes.

180403
Date: 2018-04-03
Unreal SDKs updated to support v4.17 thru 4.19
Removing support for UE 4.14 thru 4.16 (Please update!)

180329
Date: 2018-03-29
Unreal SDKs updated to support Entity APIs
Sorry for the delay!
This release still targets UE 4.17, and not 4.18 or 4.19. We are in-progress working on updating versions.

180316
Date: 2018-03-16
API changes
Entities! Blog! Quickstart Guide!
All Client login methods return Entity credentials if request.LoginTitlePlayerAccountEntity is set to true .
Guilds! Blog! Guide!
Error Codes for many API methods updated for accuracy (Dozens!).
New API methods
admin.RevokeInventoryItems and server.RevokeInventoryItems.
A whole new Entity API.
Many new Entity PlayStream Events (search for "entity" on linked page).
Most SDKs updated to support Entity APIs
Full Suppor t:
UnitySDK
JavaScriptSDK
ActionScriptSDK
CSharpSDK
NodeSDK
PostmanCollection
WindowsSDK
Cocos2d-xSDK
JavaSDK
LuaSdk (Including Corona and Defold)
PhpSdk
CloudScript
Will Suppor t Soon: Unreal Bp and Cpp. (Sorry - delayed due to technical difficulties!)

180213
Date: 2018-02-13
API changes
SendAccountRecoveryEmail now supports custom account recovery email templates when a custom account
recovery email template ID is passed in with the request parameters.
All Client Login Mechanisms can now optionally return Entity API credentials. (This is part of a coming-soon
feature.)
UnitySDK specific changes
UnitySDK
We are dropping support for older Unity versions, see our blog post.
Build files are now published using Unity version 2017.3.0f3.

180131
Date: 2018-01-31
JavaSDK changes
JavaSDK
Java is now published to Maven.

180129
Date: 2018-01-29
UnitySDK specific changes
UnitySDK
Fixing issues with compression.
It should be safe to re-enable compression for all versions and all platforms.

180123
Date: 2018-01-23
UnitySDK hotfix
UnitySDK
PlayFab UnitySDK had an issue with Unity version 2017.1.
See the forum post for details.
This has been resolved, PlayFab UnitySDK should work for all versions again.
180122
Date: 2018-01-22
API documentation update
Error codes updated on many API methods.
CSharpSDK and UnitySDK specific changes
CSharpSDK and UnitySDK
Adding a PlayFabException class, so that it's easier to catch PlayFab specific exceptions.
NodeSDK specific changes
NodeSDK
SDK Breaking Change: Require syntax for NodeSDK NPM package changed.
Major upgrade focused on NPM package.
Formerly require statements did not follow the NPM convention, requiring multiple nonstandard
require statements.
Now it requires a single require statement, and follows NPM conventions.
Major version number changed, this release is now 2.0.
1.x to 2.x Upgrade Guide.
CloudScript example
Added TypeScript definitions for the API Error exceptions.

180103
Date: 2018-01-03
LuaSDK specific updates
LuaSDK/Defold/Corona
Bug fix update.
Some platforms were producing a malformed URL which could not be resolved.

180102
Date: 2018-01-02
UnitySDK specific updates
UnitySDK
Bug fix update.
In order to avoid an issue with response headers, compression should be disabled for all device builds.
This update makes that possible.
Alternately, switching to Web Request will also avoid the issue.
A new HTTP option has been added for Unity versions > 2017.
PlayFab Release Notes 2017
5/24/2022 • 18 minutes to read • Edit Online

171204
Date: 2017-12-04
Unreal SDK changes (Cpp and Bp)
Updated both SDKs to Unreal 4.18.1 .
Older versions will still work, but require un-commenting #defines in the _.build.cs files.

171127
Date: 2017-11-27
API changes
An inventory feature allowing "Limited Edition" items is now released from beta.
This lets you define that only a fixed number of a particular itemId will be available in your game.
A virtual currency property has been removed from API methods that use "ProfileModel", as that
information was never actually provided or correct. It will return... someday.
New API methods
admin.CheckLimitedEditionItemAvailability
admin.IncrementLimitedEditionItemAvailability
client.GetPaymentToken
Used for XSolla specific payment processing
client.ReportDeviceInfo
This API method is not meant to be called directly. It is currently a built-in feature for Unity and
Lumberyard SDKs. It can be disabled with the API Policy. Additionally, we will be adding another
option soon to disable in the title settings page in Game Manager.
Updated API method error codes
client.AddOrUpdateContactEmail
client.GetLeaderboardAroundPlayer
client.LoginWithAndroidDeviceID
client.LoginWithCustomID
client.LoginWithIOSDeviceID
SDK specific updates
UnitySdk: We are now building all published unity package files with Unity 2017.2.0f3.
For testing, we internally updated to the latest for each major.minor version, from Unity 4.7.2f1 to 2017.1.2f1.
Unity Example Test Game Server: Fix applied to HttpHelper to fix SSL validation on SignalR requests.
ActionScriptSDK: AirSdk in example updated to v27.
Cocos2d-xSDK: We are still targeting 3.15.1, despite 3.16 Cocos release (stay tuned).
SdkTestingCloudScript and NodeSDK: Updated the example VS projects to support VS/msbuild 2017.
WindowsSDK: This will be the last build of the nuget package targeting Visual Studio 2013:
WindowsSdk VS 2013 Nuget Package
We are updating our automated build machines, and we won't be installing VS 2013 on the new ones.
The newer nuget package will continue to work on VS 2015 and 2017.

171106
Date: 2017-11-06
New API methods
admin.GetPlayerProfile
server.SendEmailFromTemplate
Updated PlayStream event
sent_email gains new fields: Body, and Subject.
All SDKs
MINOR SDK BREAKING CHANGE: ForgetClientCredentials() renamed to ForgetAllCredentials() .
This is part of a "coming soon" feature, which will be announced when complete.

171102
Date: 2017-11-02
New PlayFab feature
Send emails to your players, using templates.
New API methods
admin.ResetPassword
admin.GetPlayerIdFromAuthToken
client.AddOrUpdateContactEmail
client.RemoveContactEmail
server.SendCustomAccountRecoveryEmail
Documentation update
New list of error codes relevant to every PlayFab API call
Updated Error Codes for: client.LoginWithGoogleAccount, client.UpdatePlayerStatistics, server.ConsumeItem
New PlayStream events
auth_token_validated
player_updated_contact_email
sent_email
Unreal specific update
Our auto builder failed to publish the Unreal SDKs for build number 171016 and 171026. The issue with our
auto-builder has been resolved, and version 171026 has been published after the fact, and releases will
resume normally
Unity specific changes
MINOR BREAKING CHANGE: ForgetClientCredentials has been renamed to ForgetAllCredentials .
This is part of a new feature that will be coming soon. ForgetClientCredentials will be renamed to
ForgetAllCredentials in all SDKs over the next few releases.

171026
Date: 2017-10-26
API documentation changes
Updating error codes for API methods.
Many error codes that are universal to all API methods have been removed from the per-API-method list.
A new page will be made which describes universal error codes.
Removed Universal Codes:
InvalidParams
OverLimit
DataUpdateRateExceeded
AccountBanned
These errors (and others, to be published in a separate document), can be returned from any API method
and should be handled appropriately.
New error codes have been added to several dozen API methods, and a few false codes removed. The
error code lists should be much more accurate for method-specific error returns. This is still an ongoing
process, so there will be more updates.
Several API methods involving virtual currency can decrease the balance below zero. These have been
labeled appropriately.
API changes
New API methods:
admin.DeleteTitle
Hosted game servers support both IPv4 and IPv6 .
Custom game servers now support IPV6 . All newly started game server instances are assigned both
IPV4 and IPV6 addresses, which are displayed in the Game Manager Ser vers tab and returned by
the matchmaking APIs. Clients can connect to either the IPV4 or IPV6 address for the assigned server.
All API methods that return server addresses now return both options:
client.StartGame.StartGameResult
Game Manager changes
You can now delete titles using the new Admin/DeleteTitle API, or on the Game Manager studios page, as
shown below.
171016
Date: 2017-10-16
API changes
Added a parameter to server.SendPushNotification.SendPushNotificationRequest.PushNotificationPackage,
for iOS Badge.
Clarified the device-specific nature of various parameters.
New PlayStream events
player_started_purchase
player_paid_for_purchase
JavaScriptSDK specific changes
JavaScriptSDK
Our SDK now integrates with Phaser.io.
Read our tutorial Setting up PlayFab authentication in Phaser.io!
LuaSDK specific changes
LuaSDK
Our Lua publish pipeline has been fixed, and LuaSDK is being updated properly again.
UnitySdk specific changes
UnitySdk
A regression in Unity has been handled on our side, and should no longer affect PlayFab customers.
UnrealCppSdk specific changes: (UPDATED : This SDK has been deprecated. For the new unreal SDK, please
refer to UnrealMarketplaceSDK)
One of our customers has made an add-on plugin to our SDK which integrates the Unreal OnlineSubsystem
& the PlayFab SDK
You can check it out here.
Unicorn Battle example
Deleted PlayFab custom Push Plugin & Updated to FCM push messages.

170925
Date: 2017-09-05
API Changes
A handful of beta APIs that were never made public have been removed. This should not affect any current
customers or live titles.
We bypassed the default language-level header checks in our CloudScript engine. This means several
CloudScript http.request() headers that were formerly being rejected should now work.
Global Push Notification update
Please see our blog for details about the improvements to Push Notifications
New PlayStream events
player_device_info
Games using the latest UnitySDK can now see some basic analytics data about their customers. SnowFlake is
ideal for viewing and analyzing this information, but it's also available in the PlayStream Event History.
player_updated_membership
JavaScriptSDK specific changes
JavaScriptSDK
A handful of mini-features that exist in other SDKs have been added to JavaScriptSDK:
You can now inject extra headers into requests (removing one of the blockers for Double Encrypted
Logins with this SDK).
Added a new function: PlayFabClientSDK.ForgetClientCredentials()
This is a convenience function that allows you to reset the client after shutting down or logging out.
PlayFab.GenerateErrorReport()
This is a convenience function that converts the error-result from a failed PlayFab call into a single
complete description of how the call failed.
Added optional data relays into the PlayFab API requests:
result.customData
This is any contextual object you can attach to the request, which can provide context for the
result. For example, you can provide a local client-player object as the customData for an
UpdatePlayerStatistics call, and set the updated statistics on that player after the remote call
has succeeded.
result.request
The request for your API calls are now relayed to the result, which can provide context for the
result. For example, when you call UpdatePlayerStatistics , you can read the updated stats
from the request, when updating your local player object.
UnitySDK specific changes
UnitySDK
New experimental feature: This release of PlayFab UnitySDK now optionally allows you to see device
information for your players. Example information you can see is: memory, resolution, user-agent,
device-type, OS version, etc.
UnrealCppSdk specific changes: (UPDATED : This SDK has been deprecated. For the new unreal SDK, please
refer to UnrealMarketplaceSDK)
Updated to Unreal 4.17
Split apart into 3 separate plugins, each with different functionality
Pretty significant upgrades overall

170828
Date: 2017-08-28
Client API changes
client.GetCurrentGames.result.Games[i].GameServerState has been deprecated, and replaced with
GameServerStateEnum.
GameServerState was serialized as an integer, which was an error. The new field is a proper enum-string.
Other API changes
The following API methods have been deprecated on Admin and Server APIs.
GetActionsOnPlayersInSegmentTaskInstance - This has accidentally been labeled as deprecated, but
that was an error which will be reverted.
SendPushNotification can now specify TargetPlatforms
Added some clarifications for which parameters work on which platforms for SendPushNotificationRequest
(Using parameters not supported for a target platform is not recommended).
Added some info about Shared Group restrictions to the Shared Group documentation (specifically that they
can't be used for anything like Guilds).
Player Profiles can now store a player contact email address.
New PlayStream events
entity_created
entity_logged_in

170814
Date: 2017-08-14
API updates
server.GetFriendsList and client.GetFriendsList API methods now return a PlayerProfile for each of your
friends.
CSharpSdk specific updates
SDK now includes a file called NewtonSoftJsonWrapper.cs which will let you swap out our included
SimpleJson serializer with the NewtonSoft nuget package.
The file includes instructions on how to use it.

170807
Date: 2017-08-07
New API methods
admin.DeletePlayer
Deprecated API methods
These API methods never worked as fully and completely as they were supposed to. In an effort to clean this
up, we've started over, and built the new DeletePlayer API above, and these are deprecated:
admin.ResetUsers
admin.DeleteUsers

API updates
PlayerProfile (in Admin/Server/PlayStream) contains a new field ContactEmailAddresses , which contains
any email address info you may have saved about your players.
PlayStream events
New Event: auth_token_validated
New Event: player_removed_title
New Event: player_updated_contact_email
New Event: player_verified_contact_email
New Event: sent_email (Still in beta, but events are already public)
New Field in Event: player_realmoney_purchase.TransactionId
Lumber yardSdk changes:
UPGRADE WARNING: This SDK is no longer compatible with previous versions of Lumberyard.
This release of PlayFab LumberyardSdk no longer works with Lumberyard version 1.3. It has been upgraded
and now targets Lumberyard 1.9. We will very likely have it targeting 1.10 in the near future, but again
without backwards compatibility to 1.9 or earlier. See our blog for details.
UnrealCppSdk : (UPDATED : This SDK has been deprecated. For the new unreal SDK, please refer to
UnrealMarketplaceSDK).
This SDK has been discontinued, and will no longer be maintained. We will produce an upgrade guide so that
users can switch to the UnrealBlueprintSdk. Please see this blog for more details.
See our upgrade guide
Unreal SDK: (UPDATED : This SDK has been deprecated. For the new unreal SDK, please refer to
UnrealMarketplaceSDK)
The PlayFab UnrealBlueprintSdk is now rebranded as the "Unreal SDK"
Unreal SDK has been updated to 4.16, with some minor fixes
We're also removing support for older versions of Unreal, which require older versions of Visual Studio
We now support 4.14 thru 4.16
Your project may continue working for older versions of Visual Studio, but we can only support and test
Visual Studio 2015 and later
Read our blog for more info
Unity Editor Extensions
Fixed issues downloading and uploading CloudScript revisions.
Fixed issues for users whose system language uses non-ASCII letters.

170710
Date: 2017-07-10
API changes
An Enterprise feature for double-encrypted logins has been released from beta, and is now live.
New API methods:
admin.CreatePlayerSharedSecret
admin.DeletePlayerSharedSecret
admin.GetPlayerSharedSecrets
admin.SetPlayerSecret
admin.UpdatePlayerSharedSecret
client.GetTitlePublicKey
client.SetPlayerSecret
server.SetPlayerSecret
server.RegisterGameRequest has a new property: LobbyId, which will let you attempt to re-register an
existing game
server.SendPushNotificationRequest now accepts a new property: Package, which defines all of the advanced
Android push capabilities.
SDK breaking change
admin.SetupPushNotificationRequest.Platform is now defined as an enum instead of a string. This is not a
breaking change to the API (as enums are transmitted as strings), but it will require some users to convert
their strings to the enum values in their code.
Changes in all SDKs
Minor SDK Breaking Change: Most SDKs have lost an optional field in multiple requests called
UseSpecificVersion, which was an alternate way to define the adjacent Version field as null. Not all languages
have the capability to define an integer as null in the request, and this field was only meant to be useful in
relevant SDKs (Specifically Unreal). If you are using this field, just remove it, and set the adjacent Version field
to null when appropriate.
Unity EditorExtensions update
The flags panel has been updated.
ENABLE/DISABLE_IDFA flag can be toggled now.
Displays non-PlayFab flags, and allows you to remove them (use with caution, don't remove flags you need).
SDK Dependency updates
UnitySDK built, packaged, and tested with Unity2017.1.0f1.
Only trivial, non-breaking changes.
ActionScriptSDK tested with AirSDK v26.
SDK unchanged, example updated to target v26.
Cocos2d-xSDK built, and tested with Cocos 3.15.1.
Cocos 3.14->3.15 contained changes that broke our example, which in turn meant the example had to be
updated. The example still works with 3.13 thru 3.15, but the example probably won't work with older
versions of Cocos SDK unchanged, and should continue to work with most of the latest 3.X Cocos versions.

170612
Date: 2017-06-12
Documentation changes
Many small revisions to dozens of API methods for clarity
Several documentation-groupings, each which only contained a single API method, have been merged into a
single group called "Platform Specific Methods".
The "Matchmaking APIs" group has been renamed to "Matchmaking" to be consistent with other groups.
Many length-restricted string fields now describe the allowed ranges.
Changes in all SDKs
Lots of broken links in all SDK readme's have been updated and fixed.
UnitySDK specific changes
UnitySDK
We now support multiple versions of the Android API and Google Play Services. Read more details
here.
This concludes the planned changes to the Unity + Android Push-Plugin for now. Please let us know if
you have any additional requests here.

170530
Date: 2017-05-30
API changes
BREAKING CHANGE: In server.ReportPlayer, the titleId field in ReportPlayerServerRequest has been
immediately removed (not merely deprecated). All reports will now go to their own title, and cannot report
to another title.
This had to be a breaking change as it was otherwise a mild cross-title exploit. Contact us if you need
assistance with this change.
In client.ReportPlayer and server.ReportPlayer, result.Updated has been deprecated in both cases. It was
always true, and the API Call would always return an error if the player was over the report limit. This error
condition has been updated to be OverLimit to match other limits.
All login methods can now return a player profile object, if requested, which contains information previously
only available to leaderboard results.
New API methods
client.GetPlayerProfile and server.GetPlayerProfile
Returns information previously only available to leaderboard results.
Documentation
Small updates, several examples no longer contain information about deprecated fields.
ExecuteCloudScript return and log size limits defined.
New PlayStream events
gameserverhost_started
gameserverhost_stopped
player_set_profile_property
UnitySDK specific changes
UnitySDK
Our Android Push plugin has been overhauled.
Blog Post
New/Updated Guide
CSharpSDK specific changes
CSharpSDK
It is now possible to specify extra headers that will be injected into an API request.
This is an Enterprise-Only feature, specifically for double-encrypted login requests.

170508
Date: 2017-05-08
API changes
BREAKING CHANGE:
ExecuteCloudScript will not serialize the return value of your call, if it is too large.
ExecuteCloudScript will not serialize the logs for your call, if they are too large.
Under either of these conditions, the call will still return 200/successful, but the FunctionResult and/or Logs
properties will be null.
PlayStream event changes
player_vc_item_purchased and character_vc_item_purchased now contain a StoreId parameter indicating
which store was used to make a purchase.
New event:
title_profile_view_constraints_changed
CSharpSDK updates
CSharpSDK
Some unused source files in CSharpSDK have been deleted.
This should not affect any existing projects, or the Nuget package, as those files were not referenced
by the Visual Studio Solution.
Postman collection update
Several common request parameters now utilize environment variables.
Specifically, TitleId={{TitleId}}, PlayFabId={{PlayFabId}}, CharacterId={{CharacterId}}, and CatalogVersion=
{{PrimaryCatalogName}}

170424
Date: 2017-04-24
SDK hotfix release
JavaSDK Updates:
We now publish Jar files for the SDK, one for code, and one for Java docs, which you can import into
your Java project instead of copy-pasting code. Thanks to Will Iverson for helping us improve our
JavaSDK usability
UnityEditorExtensions updates:
We have resolved some install-time exceptions. Specifically it is no longer required that you restart
Unity after a first-time install.
Additionally, an issue where the Client API was sometimes disabled inappropriately is now fixed.
(edited)
UnrealCppSdk Updates: (UPDATED : This SDK has been deprecated. For the new unreal SDK, please refer
to UnrealMarketplaceSDK)
The titleId is now available from the Plugin interface

170411
Date: 2017-04-11
API changes
New Enterprise Feature: Additional login encryption
You can utilize the Policy API methods to enforce Login Calls can require a second layer of encryption
See: UpdatePolicy , specifically UpdatePolicyRequest.Statements.ApiConditions
This feature is still partially in beta, and activating it is not suggested (yet - Coming Soon!)
New PlayStream events
player_receipt_validation
UnitySDK specific changes
It is now possible to specify extra headers that will be injected into an API request (This is required for the
encrypted login calls above).
UnityEditorExtensions specific changes
Fixed a compile issue with Unity 5.6.

170406
Date: 2017-04-06
Hot Fix for Unity Android Push plugin
Fixed Android 7.0+ Crash Bug.
Fixed Android missing Large Icon support ( Lollipop + ).
Fixed Android Small Icon support on Android 7.0+ ( now supports _transparent.png ).

170403
Date: 2017-04-03
API changes
Client & Ser ver Leaderboard Methods: Get-Leaderboard methods (such as client.GetLeaderboard)
previously gained new non-nullable parameters Version and UseSpecificVersion. The requirement that they
were non-nullable was an API-breaking change. We have updated these properties to be fully optional.
Client API: The Items field of GetPurchaseResult will be deprecated: This portion of the result is often
incorrect or incomplete. It will eventually be replaced with a fully functional parameter.
New PlayStream events
player_display_name_filtered

Unreal Specific Changes: (UPDATED : This SDK has been deprecated. For the new Unreal SDK, please refer to
UnrealMarketplaceSDK)
UnrealCppSdk: An issue where PlayFab settings such as TitleId were lost when publishing a build has been
fixed. Both SDKs have been tested and verified working with Unreal 4.15
JavaSDK specific changes
JavaSDK
JavaSDK folder structure and testing has been restructured.
The internal folder structure of the repo has changed a bit to accommodate Maven best practices.
Dependencies are now Maven controlled and no longer included with the SDK.
Our internal automated testing has been converted to Maven command line.
Our SDK is NOT available on Maven Central, as that effort has faltered. There is no ETA for completion
at this time.
UnitySDK specific changes
UnitySDK
Internal Unity version for testing and building asset bundles updated to 5.6.0. Our Unity SDK remains
compatible with all versions of Unity from 4.7 thru 5.6.
A compile issue with UnityEditorExtensions in Unity 5.6 has been fixed.

170223
Date: 2017-02-22
API changes
PlayFab leaderboards now store an avatar url for every player. This can be used to reference a player image
for leaderboard entries.
All leaderboard APIs can now fetch a specific version of the leaderboard. This is for titles which are set to use
Resetting Leaderboards.
Leaderboard entries now contain the PlayerProfile which can be used to display more detailed leaderboards
without additional API calls
PlayFab can now authenticate clients using Windows Hello and validate Windows store receipts
New APIs
Client/UpdateAvatarUrl
Client/RegisterWithWindowsHello
Client/GetWindowsHelloChallenge
Client/LoginWithWindowsHello
Client/LinkWindowsHello
Client/UnlinkWindowsHello
Client/ValidateWindowsStoreReceipt
Server/SetFriendTags
New PlayStream events
player_changed_avatar
WindowsSDK specific changes
Added some missing null checks to the JSON serializer.
All SDKs
Minor additions to the testTitleData format. This only applies to the Example-Test projects that come with
SDKs.

170130
Date: 2017-01-29
Breaking changes
The folder structure for JavaScriptSDK and NodeSDK has been changed with today's major release. This may
result in some broken connections for your project when you upgrade. (File names and file contents have not
changed. New TypeScript files now exist, which did not exist before.)
API changes
Added clarifying documentation to CDN APIs. Specifically mentioning that the CDN is not part of our free
service.
Google login fixes (Blog Post Pending).
New PlayStream events
developer_logged_in
developer_registered
studio_created
studio_user_added
studio_user_invited
studio_user_removed
JavaScriptSDK specific changes
JavaScriptSDK
Release day for a major upgrade! Version number updated to 1.0.
TypeScript integration!
Repository cleanup: Separating the sdk files from the example files.
Our example project has been converted to TypeScript.
See our blog!
NodeSDK specific changes
NodeSDK
Release day for a major upgrade! Version number updated to 1.0
TypeScript integration!
Our example project has been converted to TypeScript
See our blog!
CloudScript examples
Release of a new example repository.
TypeScript integration!
See our blog!
And new repository!
We will be expanding this repository over time.
UnitySDK specific changes
UnitySDK
Fixed an issue where where JsonWrapper did not work as expected in all cases.
See our forum post for details: https://community.playfab.com/questions/7599/cloudscript-
getplayercombinedinfo-little-problem.html
All of the following deprecated wrapper classes have been removed in favor of
PlayFab.Json.JsonWrapper :
PlayFab.Json.JsonConvert (Use PlayFab.Json.JsonWrapper )
PlayFab.Json.SimpleJson (Use PlayFab.Json.JsonWrapper or PlayFab.Json.PlayFabSimpleJson )
PlayFab.SimpleJson (Use PlayFab.Json.JsonWrapper or PlayFab.Json.PlayFabSimpleJson )
Repeating a note from 160627, UnityEngine.SimpleJson is an empty namespace in the
UnityEngine.dll , and that makes it necessary for us to not use that identifier.

Unity Editor Extensions


Resolved an issue where the PlayFab panel will re-load infinitely if your account cannot view any studios.
Resolved an issue where PlayFabSharedSettings (Scriptable Object) would sometimes not save properly if
you picked your title from the PlayFab panel.

170109
Date: 2017-01-08
Breaking changes
Libs in older versions of WindowsSDK have been removed, and must be re-created in Visual Studio. Those
libs never worked in vs2015, so it's highly suggested you just update to the latest WindowsSDK, published
last week.
API changes
Fixed typos in documentation.
All SDKs
New Getting Started Guides
SDKGenerator specific changes
SDKGenerator
The ActionScriptSDK build script was inconsistent from the other SDKs. The SDKGenerator commands
that build ActionScriptSDK have been simplified to match other SDKs. (No changes to the SDK itself.)
UnitySdk specific changes
UnitySdk
Some public elements in PlayFabSettings have gained Obsolete tags:
PlayFabSettings.PlayFabSharedSettings PlayFabSettings.DefaultPlayFabApiUrl
PlayFabSettings.GetSharedSettingsObject() PlayFabSettings.ProductionEnvironmentUrl

These will be made private after a transition period.


WindowsSDK specific changes
GitHub repo has been BFG'd, and all large files have been removed from the history. Please delete your clone
or fork, and re-create it so that your history is clean.

170102
Date: 2017-01-01
API changes
Client/GetUserCombinedInfo has transitioned to fully obsolete, and has been removed from the SDK and
documentation.
Cocos2d-xSDK specific changes
Cocos2d-xSDK
Fixed a crash when a PlayFab API returns an invalid response.
Resolved some compiler warnings.
Added unit tests for lambda callback functions in our test example project.
UnitySDK specific changes
UnitySDK
We have internally updated to Unity 5.5, and our .unitypackage files are built using this version
As always, we continue to support all Unity versions 4.7 and higher.
Added static constructors to many static classes, in order to solidify the initialization sequence in
Mono2x compiler. This should resolve some of the PlayFabSharedSettings issues we've been
seeing in iOS.
IDFA/ADID will now work properly for Unity 5.6 beta.
KNOWN ISSUE: Unity 5.6 beta builds do not work on Windows Ser ver (OS ), which includes
PlayFab game-server hosting. Please contact Unity if this affects you.
WindowsSDK specific changes
Release day for a major upgrade!
Blog Post: Windows SDK Update Released
Upgrade Guide: PlayFab WindowsSdk v0.x -> v1.x Upgrade guide
PlayFab Release Notes 2016
5/24/2022 • 23 minutes to read • Edit Online

161121
Date: 2016-11-20
API changes
Each Client API can now be individually enabled or disabled.
See our blog post for details.
We are releasing a new feature called Scheduled Tasks.
See our blog post for details: (Coming soon).
New APIs
Client API Policy APIs
Admin/GetPolicy
Admin/UpdatePolicy
Scheduled Tasks
Admin/AbortTaskInstance
Admin/CreateActionsOnPlayersInSegmentTask
Admin/CreateCloudScriptTask
Admin/DeleteTask
Admin/GetActionsOnPlayersInSegmentTaskInstance
Admin/GetCloudScriptTaskInstance
Admin/GetTasks
Admin/RunTask
Admin/UpdateTask
New PlayStream event
title_permission_policy_changed
WindowsSDK specific changes
A new overhauled WindowsSDK will be published next week.
See our blog post for a brief description.
If you are interested in previewing the upcoming changes, post here:
https://community.playfab.com/questions/3973/windowsc-sdk-vs2015-support.html

161108
Date: 2016-11-07
HOTFIX
Version 1.0 of the overhauled CSharpSDK increased the .Net version requirement from 4.0 to 4.6. This was not
intended. This hotfix removes the 4.6 only features, so that it will once again build on .Net 4.0 or higher.

161107
Date: 2016-11-06
API changes
Shared
CatalogItem
InitialLimitedEditionCount ( out of beta ) If IsLImitedEdition is true , then this determines amount of the
item initially available. Note that this field is ignored if the catalog item already existed in this catalog, or the
field is less than 1.
Player display name uniqueness is now optional.
Player display name returned as Photon "Nickname" when players connect to Photon Cloud.
Ser ver API
RedeemCouponRequest
Added: CharacterId
Optional identifier for the Character that should receive the item. If null , item is added to the player.
UpdatePlayerStatisticsRequest
Added: ForceUpdate
Indicates whether the statistics provided should be set, regardless of the aggregation method
set on the statistic. Default is false .
New PlayStream events
Player_photon_session_authenticated
Title_secret_key_changed
Title_api_settings_changed

SDK changes
CSharpSDK Specific Changes:
Major CSharp upgrade

161031
Date: 2016-10-30
Unreal Blueprints hotfix release (UPDATED : This SDK has been deprecated. For the new unreal SDK, please
refer to UnrealMarketplaceSDK)
UnrealBlueprintSDK upgrade warning : There was a naming conflict between Android and the PlayFab
"SourceType" enum. As a result, we've had to rename this blueprint-enum. This breaks any
Client/GetStoreItems or Admin/GetStoreItems PlayFab-api-nodes. The upgrade process in-editor is to
delete and re-create each affected blueprint node.
UnrealBlueprintSDK Specific Changes:
Fixed a minor bug where certain errors would not report correctly
Fixed a name conflict that prevented making Android builds (ESourceType)

161017
Date: 2016-10-16
Deprecation changes
Client/GetUserCombinedInfo has transitioned from Proposed to Deprecated , which means most SDKs using
this will now throw an error. Please transition to Client/GetPlayerCombinedInfo.
Deprecated APIs from this patch note: 160822 have transitioned from deprecated to obsolete, according to
this blog: Deprecation Visibility and thus, those APIs have been removed from the newest version of the
SDKs. If you update your SDK, you must now transition to the new replacement APIs.
Password in the Admin UserCredentials object has been deprecated. You no longer need to know your user's
password to call the Admin/ResetUsers method.
UnitySdk breaking changes
UnitySdk
If you are using reflection on PlayFab API-model types, you will have to convert your reflection logic
from properties to fields (See UnitySdk Specific Changes below).
API changes
New PlayStream events:
gamelobby_started
gamelobby_ended
Client/AttributeInstall request has deprecated Android_Id and converted to Adid . All SDKs have had
some internal login hooks updated to account for this. This is not a breaking change, because it was
always intended to use Google-AdvertisingId (Adid), and using the Android DeviceId here would not
have worked properly. This change is merely for clarity and consistency
For the GitHub add-on, revisions to CloudScript will no longer immediately go live. Instead a new
revision will be made, and you make it live via Game Manager
The default helloWorld CloudScript function described in this doc: CloudScript quickstart was out of
date. Updated the document to more closely match the current version (This is only relevant to new
title creation)
API Server bug fixes
Fixed a 500 error in Server/ExecuteCloudScript: PlayFabId is now a mandatory parameter (Formerly it would
error if it wasn't provided)
Fixed a 500 error in Server/GetSharedGroupData: SharedGroupId is now a mandatory parameter (Formerly
it would error if it wasn't provided)
Fixed a 500 error in Server/AddSharedGroupMembers: PlayFabIds is now a mandatory parameter (Formerly
it would error if it wasn't provided)
Fixed a 500 error in Server/RemoveSharedGroupMembers: PlayFabIds is now a mandatory parameter
(Formerly it would error if it wasn't provided)
Fixed a 500 error in Server/DeleteSharedGroup: SharedGroupId is now a mandatory parameter (Formerly it
would error if it wasn't provided)
LuaSDK specific changes
LuaSDK
Better identification headers for Corona vs Defold.
UnitySDK specific changes
UnitySDK
Model properties have been converted to fields so they display better in the Unity Inspector (where
relevant).
Fixed a bug where if a CloudScript function returns a primitive, it will now be properly deserialized
and returned as FunctionResult (Formerly it would have been null).
The PaperTrail package has been fixed: UnityPlayFabPaperTrail.unitypackage
SDKGenerator specific changes
SDKGenerator
SDKGenerator can additionally read Api-Specs from Api-Server or GitHub, allowing customers to
build their custom SDKs in-sync with PlayFab api-server, and with fewer steps and dependencies.

161003
Date: 2016-10-02
API changes
New APIs
Client/GetTime
Server/GetTime
Google OAuth upgraded to v3
Improved search results on our documentation site: PlayFab Documentation.
SDK global changes
Revised documentation for examples in SDKs, and provided better explanations of how to use our testing
tools:
https://github.com/PlayFab/SDKGenerator/blob/master/JenkinsConsoleUtility/testTitleData.md
https://github.com/PlayFab/SDKGenerator/blob/master/JenkinsConsoleUtility/readme.md
LuaSdk specific changes
LuaSdk
Corona Plugins are now available from the Corona Marketplace.
Client Plugin: https://marketplace.coronalabs.com/plugin/playfab-client
Server Plugin: https://marketplace.coronalabs.com/plugin/playfab-server
Combo Plugin: https://marketplace.coronalabs.com/plugin/playfab-combo
Corona Readme: https://github.com/PlayFab/LuaSdk/tree/master/Corona
UnitySDK specific changes
UnitySDK
UnitySDK V0 repository is being retired. Everybody should please update to UnitySDK V2 available on
our download page.
IDFA and AdvertisingId will work properly on Unity 5.5 beta versions.
CloudScript functions that return a primitive, such as an integer, will now deserialize correctly
Minor improvements to Unity Compression, it should now be safe to enable compression in the
PlayFabSharedSettings scriptable object.
WindowsSDK specific problems
The .lib files published with this repo are now bigger than the GitHub max file-size limit.
The latest version does not have updated lib files, and we've begun looking at alternatives.

160919
Date: 2016-09-18
New APIs for payments
We are expanding our Payments API to include a standard way to refund and dispute purchases.
Admin/RefundPurchase
Admin/ResolvePurchaseDispute A few friend-based APIs have been copied from the Client to
the Ser ver :
Server/GetFriendLeaderboard
Server/AddFriend
Server/GetFriendsList
Server/RemoveFriend
Small improvements to the Matchmaking ability of our Server API
Server/RegisterGame
Server/DeregisterGame
Server/SetGameServerInstanceTags
Server/RefreshGameServerInstanceHeartbeat
Cocos2d-xSDK specific changes
Cocos2d-xSDK
Cocos sample updated triggering a rebuild of the example project. This should still work as previously
designed, as only cosmetic changes were applied.
UnitySDK specific changes
UnitySDK
Minor fixes in unity game server, to reflect API changes.
JavaScriptSDK specific changes
JavaScriptSDK
Test-example updated to use CDN.

160912
Date: 2016-09-11
Unity and CSharp upgrade warning
The deprecation warnings described below have gone into effect. Deprecated APIs will now throw compiler
errors when possible. Likewise, the documentation for those APIs have been filtered from the main
documentation.
API changes
New APIs
Admin/GetAllActionGroups
Server/GetAllActionGroups

LuaSDK specific changes


LuaSDK
Incremental Corona Support: There are new/interim zip-files which can be included in a Corona
project. Proper Corona plugins are coming soon.

160829
Date: 2016-08-28
API changes
New APIs
Client/GetPlayerTags
Server/AddPlayerTag
Server/GetPlayerTags
Server/RemovePlayerTag
Admin/AddPlayerTag
Admin/GetPlayerTags
Admin/RemovePlayerTag
We have introduced segment tags, which provide a way of directly putting players into particular segments. You
can now add one or more segment tags to each player. And then, when creating a segment, you can define the
segment based on the segment tag.
One intended use for Segment Tags is for integration with external analytics providers, like Appuri. The external
analytics provider can perform its own advanced segmentation, such as "Likely to Churn", and then set a tag on
players that match that segment. All current deprecation changes have been released. Please see our blog post
for details: https://playfab.com/deprecation-visibility/
Cocos2d-xSDK specific changes
Cocos2d-xSDK
Special thanks to Max Muthig from Forest Ring Games for the following update:
Added support for lambda callback functions (formerly only static functions were allowed).
PostmanCollection specific changes
PostmanCollection
Added a header to all API methods which will help our servers track SDK usage. (This header already
exists on all other SDKs).
UnitySDK specific changes
UnitySDK
We are pleased to announce the initial public beta release of our latest tool: Unity Editor Extensions.
This plugin provides an easy-to-use interface for configuring and managing the PlayFab SDK. All Unity
developers are encouraged to check out EdEx; There has never been an easier time to sign up and get
started developing.
Added an alternate implementation of ExecuteCloudScript which automatically parses
FunctionResult into a target type, using a generic parameter.
Failure cases in API methods are improved: Some cases that threw exceptions now properly report
back to the error-callback (such as Web-Requests with no internet connection), and other cases report
better information to the error-callback.
UnrealBlueprintSdk specific changes: (UPDATED : This SDK has been deprecated. For the new unreal SDK,
please refer to UnrealMarketplaceSDK)
Fixed an issue where APIs containing an optional list field in the request would not post the request properly
to the server. (Such as GetPlayerStatistics)
SDKGenerator specific changes
SDKGenerator
Updated documentation, and an example project to better document for PlayFab users how to create
their own SDKs for our API.

160822
Date: 2016-08-21
Global upgrade warning
Some SDKs have gained warnings for APIs that have become deprecated. If you see these warnings, please
resolve them ASAP, and migrate to the indicated replacement APIs. Many of these APIs will be removed from the
SDK within the next couple of months. There is a blog post about this here.
Deprecation notices
Admin Fields
UpdateCloudScriptRequest.Version
Client Fields
GetPlayFabIDsFromSteamIDsRequest.SteamIDs
SendAccountRecoveryEmailRequest.PublisherId
SteamPlayFabIdPair.SteamId
Client DataTypes
GetCloudScriptUrlRequest
GetCloudScriptUrlResult
GetFriendLeaderboardAroundCurrentUserRequest
GetFriendLeaderboardAroundCurrentUserResult
GetLeaderboardAroundCurrentUserRequest
GetLeaderboardAroundCurrentUserResult
GetUserCombinedInfoRequest
GetUserCombinedInfoResult
GetUserStatisticsRequest
GetUserStatisticsResult
LogEventRequest
LogEventResult
UpdateUserStatisticsRequest
UpdateUserStatisticsResult
Client APIs
GetUserCombinedInfo
GetFriendLeaderboardAroundCurrentUser
GetLeaderboardAroundCurrentUser
GetUserStatistics
UpdateUserStatistics
LogEvent
GetCloudScriptUrl
RunCloudScript
Ser ver Fields
GetPlayFabIDsFromSteamIDsRequest.SteamIDs
SteamPlayFabIdPair.SteamId
Ser ver DataTypes
GetUserStatisticsRequest
GetUserStatisticsResult
LogEventRequest
LogEventResult
UpdateUserStatisticsRequest
UpdateUserStatisticsResult
Ser ver APIs
GetUserStatistics
UpdateUserStatistics
LogEvent

API changes
New APIs
Admin/BanUsers
Admin/GetUserBans
Admin/RevokeAllBansForUser
Admin/RevokeBans
Admin/UpdateBans
Admin/DeleteStore
Server/BanUsers
Server/GetUserBans
Server/RevokeAllBansForUser
Server/RevokeBans
Server/UpdateBans
Server/GetRandomResultTables
New PlayStream events
player_tag_added
player_tag_removed
title_catalog_updated
title_store_updated
Global SDK changes
The example projects provided with the SDKs have all been updated, and no longer use deprecated APIs.
Several SDKs have compiler warnings and/or comments that describe deprecated elements of the API.
The PostmanCollection internal format changed slightly. It will be less convenient to have multiple future
versions of our PostmanCollection loaded at the same time (You'll get a warning about duplicate IDs).
ActionScriptSDK specific changes
ActionScriptSDK
Updated Adobe AirSdk in the example project from version 18 to 22.

160815
Date: 2016-08-14
Unreal upgrade warning
Required syntax changes for upgrading Unreal 4.12 Best described by ZKShao in the pull request which helped
resolve the problems: https://github.com/PlayFab/UnrealCppSdk/pull/32
API changes
Minor documentation updates.
New PlayStream events:
player_statistic_deleted
player_unlinked_account
UnrealCppSdk & UnrealBlueprintSdk specific changes: (UPDATED : These SDKs have been deprecated.
For the new unreal SDK, please refer to UnrealMarketplaceSDK)
Updated to support Unreal 4.12
Sadly, this requires dropping support for Unreal 4.11.x, due to conflicting requirements
Support for Unreal 4.9 is maintained
UnitySDK specific changes
UnitySDK
Pre-Alpha release of a live-connection: Subscribe your custom game servers to live PlayStream events
using SignalR
Game-servers can begin testing with registering callbacks to PlayStream events, and react in real-time
PlayFabSDK no longer requires permissions on Android. (WP8 and iOS still requires internet in build
settings)
Phasing in deprecation warnings for APIs are out of date.
These will later become deprecation errors, and will eventually be removed from the sdk.
Some bug fixes for compression
PlayFabSdk now works in Unity 5.0
Fixed specific devices on specific older unity versions, and expanded internal testing
Updated UUnit test framework to display correctly when an async test times out
Our asset bundles are built with Unity 5.4

160801
Date: 2016-07-31
API changes
New APIs
RemoveVirtualCurrencyTypes
GetAllSegments
GetPlayerSegments
GetPlayersInSegment
GetPlayerCombinedInfo
GetAllSegments
GetPlayerSegments
GetPlayersInSegment
New PlayStream Events
session_started
session_ended
Minor documentation updates.

160726
Date: 2016-07-25
UnitySDK hotfix changes
UnitySDK
Fixes for specific Devices on older Unity versions.
Fix for specific AdminApi model classes which were being labeled as PlayFabResultCommon instead of
PlayFabRequestCommon .
Known Issue: When using PlayFab UnitySdk, Google advertisingID and iOS IDFA no longer attribute
correctly for Unity versions before 5.3.
The easiest fix is to upgrade your Unity3D version, but we will try to restore this in a later release of
our SDK.

160725
Date: 2016-07-24
API changes
New PlayStream Event
display_name_filtered (documentation available soon).
Some API examples have been updated.
Lots of minor documentation updates.
UnitySDK specific changes
UnitySDK
Introduced a PlayFabRequestCommon base-class , which does compile-time type-checking for
request objects passed to the API (This should not affect any users unless they're using non-
standard request objects).
Fixed a null-reference bug in startup that some users have reported.
Fixed an issue with ProductionEnvironmentUrl in the PlayFabSharedSettings ScriptableObject that
some users have reported.

160721
Date: 2016-07-20
UnitySDK hotfix changes
UnitySDK
Unity 4.7 works again, within the limitations of that version
A bunch of small high-visibility fixes that have been noticed by many in the community have been
fixed.
UnitySDK V2 was promised to have full Windows Phone/Universal support (as well as other
platforms like consoles). We're happy to say that all known issues have finally been fixed for all
known platforms, and the PlayFab UnitySdk should work everywhere.
Due to an unexpected side-effect in Unity, we won't be able to apply the HideAndDontSave flag to
the PlayFab Http Object. Details Here.
We have added a set of extension functions to reflection, which make both standard C# and
.NetCore C# do the same thing with the same lines of code, when possible. This extension it is not
meant to be a complete solution for all possible reflection inconsistencies between those
platforms.

160714
Date: 2016-07-13
UnitySDK upgrade warning
UnitySDK
We have released a new major revision for UnitySDK. Please visit our Upgrade Guide (UPDATE : The
UPGRADE Guide is obsolete).
API changes
You can now set CustomData on an item when granting it via the Admin Api: GrantItemsToUsers,
specifically: ItemGrant.
Twitch login integration! and APIs:
LoginWithTwitch
LinkTwitch
UnlinkTwitch
GetPlayFabIDsFromTwitchIDs
New PlayStream Events:
title_exceeded_limit
title_limit_changed
title_requested_limit_change
LumberyardSDK specific changes
Updated to Lumberyard 1.3
UnitySDK specific changes
UnitySDK
A new major revision of UnitySdk is going to be released very soon (hopefully today).
The original UnitySdk will be available here for a limited time [UPDATE: Old link removed].
Version 2 of the UnitySdk is currently available here: UnitySDKV2Beta [UPDATE: Old link removed],
and will become the new UnitySdk soon [UPDATE: Done].

160705
Date: 2016-07-04
API changes
New API
GetPlayerCombinedInfo
Lots of updated descriptions.
All login calls have been updated to optionally return the GetPlayerCombinedInfo results.
GetUserCombinedInfo API will be deprecated in favor of GetPlayerCombinedInfo in the near future.

UnitySDK specific changes


GZip compression mode has been restored for api-requests done with
PlayFabSettings.RequestType = WebRequestType.UnityWww ;

A JsonProperty attribute has been added to SimpleJson and supports alternate naming of
fields/properties, and omitting nulls from the serialized json.
TimeSpans serialized with the default PlayFab SimpleJson strategy will now serialize as a float number of
seconds. Formerly, they would serialize as structs which wasn't supported by the API or any cross-
platform options.
Support for certain platforms (EG: consoles, iOS) that build using Mono2x mode will not be supported
until https://github.com/PlayFab/UnitySDKV2Beta goes live.
Support for Windows Universal will not be supported until https://github.com/PlayFab/UnitySDKV2Beta
goes live.
See this blog post for more details: https://playfab.com/new-and-improved-unity-sdk-beta-preview/
(standalone and android work correctly and are supported for all options)
All platforms that can utilize IL2CPP are supported in that mode.
This version was initially launched with an issue where compression did not always work. It was hot-fixed
on July-8. Initial downloads before this date may have compression issues, which can be solved by
updating, or by disabling compression: (PlayFabSettings.CompressApiData = false;)

160627
Date: 2016-06-26
UnitySDK upgrade warning
UnitySDK
has been renamed to PlayFab.Internal.PlayFabUtil . The "Util" name is
PlayFab.Internal.Util
very common and exists in the root level for many projects, which causes name conflicts for those
customers.
When updating PlayFab-UnitySdk, you may see some deprecation warnings if you are using
PlayFab's implementation of SimpleJson. Please resolve these at your leisure.
API changes
New Admin APIs
GetTitleInternalData
SetTitleInternalData
New PlayStream events
character_consumed_item
character_created
character_inventory_item_added
character_statistic_changed
character_vc_item_purchased
character_virtual_currency_balance_changed
player_redeemed_coupon
UnitySDK specific changes
UnitySDK
Known issues: Windows Store apps, and non-IL2CPP build options do not work yet. Stay tuned for a
blog post about these issues and our new repository: UnitySDKV2Beta [UPDATE: Old link removed].
We discovered a name-conflict with the core UnityEngine DLL, specifically an empty namespace
called SimpleJson . As such, we've had to rename and reorganize our JSON classes... again. Many
apologies.

160613
Date: 2016-06-12
Global SDK upgrade warning
PlayFabSettings and PlayFabVersion: These files and their contents have been merged into PlayFabSettings.
If you were previously referencing the PlayFabVersion variables, update to the same/very-similar variable in
PlayFabSettings.
API changes
New API
SetGameServerInstanceData
Bug fix for APIs:
Server/SetGameServerInstanceState
Client/GetCurrentGames
SDK global changes
Please note that RunCloudScript has been deprecated since March 2016, and will be removed from the
sdks in the near future. Please convert to ExecuteCloudScript asap.
Please stay tuned for a blog post about an internal testing system we call Jenkernaught. Our example
projects contain some changes oriented towards deeper testing to improve sdk stability and reliability.
Some specifics:
All testing and examples for CloudScript have been updated to ExecuteCloudScript, since RunCloudScript
is deprecated.
All testing and examples for successful login have been updated to LoginWithCustomID , to make internal
testing easier.
Cocos2d-xSDK specific changes
Cocos2d-xSDK
MultitypeVar can contain a PlayFabBaseModel for the purposes of writing request objects. It still
cannot receive an arbitrary json object for results.
Initial versioned release.
UnrealBlueprintSdk specific changes: (UPDATED : This SDK has been deprecated. For the new unreal SDK,
please refer to UnrealMarketplaceSDK)
Removed version info from a bunch of header-comments to avoid spammy check ins (So, this is the last
spammy check in)
A missing http header is now provided.

160606
Date: 2016-06-05
Global SDK upgrade warning
For consistency across all sdks, the sdkRevision variable was renamed to sdkVersion (ActionScriptSDK,
JavaSDK, UnitySdk). If you were accessing sdkRevision , switch to sdkVersion .
API changes
Some documentation updates, and improved error notifications.
SDK global changes
More steps towards the deprecation of RunCloudScript , so customers should plan to migrate to
ExecuteCloudScript for live projects.
Internally, we are halfway through a push to improve testing multi-platform testing for all sdks.
SDKGenerator users may find references to Jenkernaught and buildIdentifier . Jenkernaught is the
code-name for the tech that enables this improved platform testing. buildIdentifier is a new variable in
all sdks indicating the specific PlayFab-Jenkins job which generated a particular sdk version.
There will be blog-post describing what the Jenkernaught does, and more detailed test-framework
changes omitted from here, so stay tuned.
ActionScriptSDK specific changes
ActionScriptSDK
Jenkernaught -related ASyncUnitTest framework changes in the example/testing project.

CSharpSDK specific changes


CSharpSDK
To mirror UnitySDK, we're moving the json-specific code from PlayFabSettings to PlayFabUtil . We've
also expanded PlayFabUtil to be closer to feature parity with UnitySDK.
Improved documentation in the remaining PlayFabSettings options, for clarity.
Jenkernaught related Unit framework changes in the example/testing project.

JavaScriptSDK specific changes


JavaScriptSDK
Added a utility function to the PlayFabClientSDK: IsClientLoggedIn() . Please use this to determine this
condition.
Minor Jenkernaught related test-changes example/testing project.
NodeSDK specific changes
NodeSDK
Added a utility function to the PlayFabClientSDK: IsClientLoggedIn() . Please use this to determine this
condition.
Minor Jenkernaught related test-changes example/testing project.
UnitySDK specific changes
UnitySDK
Fixed a critical bug where PlayFab API calls would stop working if you changed scenes.
Adjusted the defaults for timestamp formats to be consistent with other PlayFab SDKs.
We are still having issues with Windows-Phone and Windows-Universal for Unity versions 5.3 or
higher, which we hope to fix soon.

160523
Date: 2016-05-22
Global SDK upgrade warning
Various APIs that save versioned data (UserData, CharacterData, and others) have had a datatype change from
int to uint. This will require some users to remove/alter some casting where our api was formerly inconsistent.
Some developers may need to change some local variables from int to uint.
UnrealBlueprintSdk upgrade warning: There was a naming conflict between xcode and some of the playfab
enums. As a result, we've had to revise the blueprint-enums again, which breaks all PlayFab-api-nodes using
enums. The upgrade process in-editor is to delete and re-create each affected blueprint node (they will throw in-
editor-compiler warnings if they're affected). (UPDATED : This SDK has been deprecated. For the new unreal SDK,
please refer to UnrealMarketplaceSDK)
API changes
There were some DataVersion vars which were set to an inconsistent datatype (int and uint in various
APIs). All of these have been changed to uint for consistency.
Some additional options have been added to APIs related to Matchmaking.
The matchmaker now takes an additional parameter ( StartNewIfNoneFound ), which allows titles to
determine whether a new server should spin up if no results are found in the matchmaking process. By
default, StartNewIfNoneFound is true , meaning that a new session will be created if one cannot be found
which matches the requirements. This allows titles with skill-based matchmaking to potentially "loosen"
the requirements for a match, to get players with skill levels at the far ends of the bell curve into games
more quickly.
Updated the custom game server logic with GameInstanceState , which determines whether the game
session is available for matchmaking. Games which are Closed are not available for matchmaking,
allowing developers to create game sessions which are specific to a group of players, as well as to
prevent post-start joins of a game session in progress. By default, game servers start in an Open state.
New API: SetGameServerInstanceState call can be used by the server to set its state, and StartOpen
has been added to the GameModeInfo used in calls to ModifyMatchmakerGameModes , to allow specifying
whether sessions in a game mode start as Open (the default) or Closed .

UnrealBlueprintSdk specific changes: (UPDATED : This SDK has been deprecated. For the new unreal SDK,
please refer to UnrealMarketplaceSDK)
Internal SDK updates that make it easier to execute and handle API calls from C++.
Added an internal testing suite which allows thorough verification of PlayFab functionality on all target
devices. (Example project only, not the core plugin)
A bunch of C++ code cleanup, and improvements on logging and warnings.
Resolved a concurrency problem with multiple synchronous api calls for Blueprints and C++ calls.

160502
Date: 2016-05-01
Global SDK upgrade warning
If you were previously setting the ConfirmationMessage and ForceLink fields, simply remove them.
API changes
New Admin API:
SetStoreSegmentOverrides (UPDATE : This API has been removed)
Some deprecated and internal fields are no longer published with the SDK: ConfirmationMessage and
ForceLink.
UnrealBlueprintSdk specific changes: (UPDATED : This SDK has been deprecated. For the new unreal SDK,
please refer to UnrealMarketplaceSDK)
Revised the readme and the example project to use a simpler login process, and the new simpler
ExecuteCloudScript method.
When there is an api error, the details of that error will report more accurately and display better debug
information.
We are removing the "Beta" flagging from Unreal sdks, they are now a full member of our SDK collection,
with full support and quality checks.

160425
Date: 2016-04-24
UnrealBlueprintSdk Upgrade warning: Many blueprint-api-calls which have enum fields will have to be
updated to utilize the enum dropdown. The old value will be lost, and must be re-set. This affects dozens of
PlayFab blueprint nodes. (UPDATED : This SDK has been deprecated. For the new unreal SDK, please refer to
UnrealMarketplaceSDK)
API changes
Lots of documentation updates.
Fixed typo in AndroidDevicePushNotificationRegistrationRequest .
New server API:
EvaluateRandomResultTable
Cocos2d-xSDK specific changes
Cocos2d-xSDK
Cocos SDK has been overhauled.
New testing framework, internal Http functionality has been converted.
Android, iOS, and Win32 platforms are all working.
Lots of other small fixes and improvements.
UnrealBlueprintSdk specific changes: (UPDATED : This SDK has been deprecated. For the new unreal SDK,
please refer to UnrealMarketplaceSDK)
UnrealBlueprintSdk is nearing the end of its limited-support Beta period. As such, there will be some
potentially breaking changes in the next few releases.
There are data fields in the Api-specification defined as enums. Formerly, UnrealBlueprintSdk displayed these
fields as arbitrary strings, and the user was expected to input the correct option. This has been fixed. All these
fields have been converted to be enum-dropdowns in the blueprints.

160414
Date: 2016-04-13
API changes
PlayStream APIs are now available in the SDKs.
Some documentation revisions.
UnitySDK specific changes
UnitySDK
More automated testing to improve stability of SDKs (and some associated bug fixes)
Specifically, a new PlayStream test and making tests more consistent across all sdks.

160328
Date: 2016-03-27
API changes
Minor incremental improvements to the new Resettable-Leaderboards and other Player-Statistics tweaks.
Minor revisions in the way that CloudScript is uploaded via Admin-API.
Continuing to revise and define API limits and overage definitions where needed.
"PlayFabId" input has been removed from the documentation on a few client APIs, which never used that
value.
Lots of minor documentation updates.
New ExecuteCloudScript API, which replaces the older pattern of GetCloudScriptUrl+RunCloudScript .
This should make it easier for novice users to call CloudScript correctly.
Cocos2d-xSDK specific changes
Cocos2d-xSDK
Project folder structure updated to be consistent across all platforms.
This fixes the issue where iOS build would fail to import some code files.
Cocos is now tested and working for Win32 and iOS.
UnitySDK specific changes
UnitySDK
Fixing inconsistent #define options which led to errors with ReadAllText function.
Known Issue (not resolved): SimpleJson does not serialize correctly when using the Player Setting
Scripting Back end option: Mono2x . Until this is fixed, please use IL2CPP if possible.
(A similar issue may be present when building for PlayStation®.)

160307
Date: 2016-03-06
API changes
Added Server.GetPlayFabIDsFromSteamIDs .
Fixed a minor bug in Server.GetPlayerStatistics .
UnitySDK specific changes
UnitySDK
Minor SDK refactoring for building to multiple targets.
WindowsSDK & Cocos2d-xSDK specific changes
WindowsSDK & Cocos2d-xSDK
Minor SDK refactoring for building to multiple targets.
Renamed several types to be more consistent with other SDKs.
SDK additions
Amazon's LumberyardSdk now available!

160222
Date: 2016-02-21
API changes
Added Server.GetPlayFabIDsFromSteamIDs .
Fixed a minor bug in Server.GetPlayerStatistics .
Fixed a minor bug in Server.UpdatePlayerStatistics .
CSharpSDK specific changes
CSharpSDK
Updated Helper Function Signatures in the testing harness.
Updated Server CloudScript Helper classes.
UnitySDK specific changes
UnitySDK
Updated Helper Function Signatures in the testing harness.
Added structural changes to switch our internal JSON serializer from JSON.net to SimpleJson (This is
an effort to enable Universal Windows Builds).

160215
Date: 2016-02-14
API changes
Resettable Leaderboards and Player Statistics are now live.
GetPlayFabIDsFromSteamIDs accepts and returns string IDs for languages that cannot handle ulong values.
Minor changes to support Parse migrations.
Minor documentation adjustments.

160208
Date: 2016-02-07
API changes
SteamID types updated from Uint32 to Uint64 .
Added APIs
server.UnlockContainerInstance
server.UnlockContainerItem
server.UnlockContainerItem
server.UnlockContainerInstance
Added admin.StatisticResetIntervalOption for use in resetable leaderboards.
UnitySdk specific changes
UnitySdk
Modified the project folder structure a bit, which may cause some file conflicts. Please see this forum
post for details.

160201
Date: 2016-01-31
API changes
New APIs
server.ConsumeItem
SteamID types updated from Uint64 to Uint32 .
GetContentListResult ItemCounts updated from Int64 to Int32 .
UnitySDK specific changes
UnitySDK
Added a new event callback system for monitoring PlayFab API requests and responses.
160125
Date: 2016-01-24
API changes
New APIs
Client.GetPlayFabIDsFromKongregateIDs
Client.GetCharacterStatistics
Client.UpdateCharacterStatistics
Server.RevokeInventoryItem
Fixed typo in PurchaseItem___ -> PurchaseItem___ .
Updated UserAccountInfo to contain additional account details.

UnrealBlueprintSdk specific changes: (UPDATED : This SDK has been deprecated. For the new unreal SDK,
please refer to UnrealMarketplaceSDK)
Fixed a Client issue that prevented subsequent calls after login from working.

160118
Date: 2016-01-17
API changes
New leaderboard apis are available:
GetLeaderboardAroundPlayer
GetFriendLeaderboardAroundPlayer
Old leaderboard apis are deprecated:
GetFriendLeaderboardAroundCurrentUser
GetLeaderboardAroundCurrentUser
Lots of minor documentation improvements.
ActionScriptSDK specific changes
ActionScriptSDK
Fixed an issue where errorDetails where not accessible in error-callbacks.
JavaSDK specific changes
JavaSDK
AndroidStudioExample : The Android advertisingId is automatically fetched and sent to PlayFab when
appropriate (and only when appropriate).
UnitySDK specific changes
UnitySDK
Deleted some internal testing systems (DemoScene folder) from the public SDK.
We are prototyping new samples and event systems. Some of the underlying SDK changes are visible
in the diff, but none of it is accessible yet. Stay tuned as it's almost done.
An alternate version of the unit-tests are available on the client, with client-only api calls.
Cocos2d-xSDK & WindowsSDK/C++ specific changes
Cocos2d-xSDK & WindowsSDK/C++
Updated both to use RapidJson 1.0.2 (C++ syntax and code where relevant)
Some other fixes, including IOS
courtesy of https://mingle-games.com/
PlayFab Release Notes 2015
5/24/2022 • 8 minutes to read • Edit Online

151221
Date: 2015-12-20
JavaSDK specific changes
JavaSDK
Google advertisingId is now automatically fetched appropriately when required.
NodeSDK specific changes
NodeSDK
0.7.151210 release has been hot-fixed with a minor bug fix.

151210
Date: 2015-12-08
API changes
Revamped APIs for PlayerStatistic .
Xbox authentication.
PS4 authentication.
Minor documentation improvements.
SDKGenerator revamped, code cleanup in generator and all SDKs, better client/server SDK-separation.
New automated tests in all SDKs for upcoming features.
WindowsSDK/C++/Cocos2d-xSDK specific changes
WindowsSDK/C++/Cocos2d-xSDK
The structure of the SDK has changed. Users that update from an older version will need to do a bit
more work than usual.
UnitySDK specific changes
UnitySDK
Google adver tisingId and iOS IDFA will be automatically fetched appropriately in the next release.
Specific Hotfix (Dec 11, 2015)
UnitySDK
Google adver tisingId and iOS IDFA are now automatically fetched appropriately when required.

151130
Date: 2015-11-29
API changes
LoginWithGameCenter - This was previously published and now being un-hidden.
GetLeaderboardAroundUser - Some issues with returning the correct number of results have been fixed.
GetFriendLeaderboardAroundUser - New API method that acts like GetLeaderboardAroundUser , except restricts
leaderboard results to the current player's friend list.
General Login - New data is being returned for all login results. This is still in prototype, and not fully
functional yet. Stay tuned!

151123
Date: 2015-11-22
API changes
The Steam error message response has been improved.
Updated automated testing systems for SDKs.
Minor documentation updates.
ActionScriptSDK specific changes
ActionScriptSDK
Fixed a minor typo in the test-debug output.
Cocos2d-xSDK specific changes
Cocos2d-xSDK
The example project is being built with a newer version of cocos. 3.7 -> 3.8.1.
JavaSDK specific changes
JavaSDK
Re-arranged the file structure to be more web-standard.
Added a client-only AndroidStudio example project.
Minor changes to confirm this example builds and works.
Some customization to the Client/Server/Combo files to more closely match each purpose, without
extra variables/functions.
General cleanup.
PostmanCollection specific changes
PostmanCollection
Fixing server/admin authentication issues.
UnitySDK specific changes
UnitySDK
Manifest cleanup in Android Plugin.

151116
Date: 2015-11-15
API changes
Documentation updates.
The format for the version numbering has slightly changed.
PostmanCollection specific changes
PostmanCollection
Initial release of Postman Versioned Collection.
151109
Date: 2015-11-08
API changes
Some data usage caps are enforced better, and reported better when broken.
Minor documentation changes.
New API-RedeemCouponRequest:
RedeemCoupon API Documentation
Fix issue with Steam item ID's needing to be numeric strings.
Improved error reporting for OpenGraph products.
Added third party request utilities to track error rates and response times from third party APIs such as
Google Play and Facebook.
WindowsSDK specific changes
UserData , CharacterData , ItemCustomData , SharedGroupData , as well as Read-Only and Server-Only variants,
can now be deleted by using the KeysToRemove field in the Data-Update Request objects.

151026
Date: 2015-10-25
API changes
Lots of improvements behind the scenes, but none are public-facing.
API_Specs contains much more information that can be used to generate more complete documentation
and examples in the future.
Greatly sped up granting of large sets of items.

151019
Date: 2015-10-18
API changes
Several API descriptions have been updated.
Several SeeAlso links have been updated.
The FailedByUber transaction-error has been deprecated, and
The FailedByPlayFab transaction-error replaces it.
Improved studio management in Game Manager.
Added real time metric counters for API call rates, sizes and timing.
UnitySDK specific changes
UnitySDK
Removing support for Unity 4.x. All future updates will only be supported with Unity 5.x or higher:
Unity Blog.
Clean up of files that should no longer exist in the Client-SDK.
Clean up of editor-dropdown options, and fixing the documentation links.
First pass at in-depth PlayFab API usage examples. These are not polished for general release, but
experienced users may be interested in looking at an early version.
Updated Android GCM plugin to improve usability:
Added comments where appropriate.
Renamed variables to better reflect their use.
Functionality:
Fixed an issue that caused a null ref when not properly instantiated.
Fixed an issue that was hiding the public methods when built for the Android target.

151012
Date: 2015-10-11
API changes
Removed ability to delete VC definitions in Game Manager to match APIs.
Added back end code to support atomic increment/decrement.
Changed custom data versions to use new atomic increments.
Fixed issue where user's VC would roll over if passing Int32 max. Now VC is capped to Int32 max.
Added support for case sensitive VC names to prevent rare issue.

151005
Date: 2015-10-04
API changes
Fixed PSN issue not properly using proxies.
Added character inventory management to Game Manager.

150928
Date: 2015-09-27
API changes
Client/Ser ver-API : GetCharacterInventory can return a new error type: CharacterNotFound .
Admin-API : RevokeInventoryItemRequest can operate on a character-inventory by providing a Character ID
in the request.
All : Very minor API documentation updates.
Bypass cache when GetUserData API calls specified filtering keys.
Added optional Character ID to revoke item API calls.
Fixed versioned data calls returning null instead of empty.
Changed APIs to restrict virtual currency names to 2 characters.
ActionScriptSDK specific changes
ActionScriptSDK
Initial release of ActionScript Versioned SDK.
Cocos2d-xSDK specific changes
Cocos2d-xSDK
Added a CloudScript test.
CSharpSDK specific changes
CSharpSDK
Minor updates to unit-testing framework.
Added a CloudScript test.
JavaSDK specific changes
JavaSDK
CloudScript fixes, added a CloudScript JUnit test.
Better error-reporting for bad/failed api calls.
UnitySDK specific changes
UnitySDK
Minor updates to unit-testing framework.
Added a CloudScript test.
Fixes to Android push-notifications.
WindowsSDK/C++ specific changes
Added a CloudScript test.

150921
Date: 2015-09-20
API changes
All-APIs : Minor function-documentation changes.
All-APIs : CatalogItem gains an optional parameter linked to Facebook purchasing.
Client and Ser ver API : VC recharge times are added to GetCharacterInventoryResult .
Client-API : LinkFacebookAccountRequest gains an optional parameter to override old connections.
Client-API : LinkKongregateAccountRequest and LoginWithKongregateRequest parameters are fixed.
Removed [a-zA-Z0-9] regex for character names.
Improved internal error handling to prevent returning unhelpful server errors.
Added tests to verify CDN APIs work as described.
Changed AddFriend API, to prevent you from adding yourself as a friend.
Fixed issue where AddFriend server API always returned an error.
Updated push notification internal code to report better errors from the remote push service.
Fixed error counts in API usage report which would not report some errors on the summary but would show
them in the details.
Added rate limiting to CloudScript and added ability for CloudScript -> PlayFab API calls to bypass rate
limiter

150908
Date: 2015-09-07
API changes
Some APIs returned a UserisNotValid error, this error has been renamed to AccountNotFound .
Better integration for matching PlayFab IDs and Facebook IDs, and matching them to the same account.
Server API's now define the client GetTitleNews API.
Feature not configured errors separated into more specific errors such as Facebook not configured .
Improved errors around Paypal API exceptions.
Fixed issues with coupon creation.
UnitySDK specific changes
UnitySDK
Fixed some IOS build issues.
Slight documentation improvements.
Android GCM fixes/updates.

150901
Date: 2015-08-31
API changes
New Client API :
ListUsersCharacters
ConsumeItemRequest takes an optional CharacterId parameter.
PurchaseItemRequest takes an optional CharacterId parameter.
UnlockContainerItemRequest takes an optional CharacterId parameter.
PurchaseItem can now return a new error type, CharacterNotFound , when a CharacterId is provided.
UnlockContainerItem function documentation updated.
Client and Ser ver : GetCharacterInventoryRequest parameter, PlayFabId , is now optional.
Added tracking of identity provider across login history.
UnitySDK specific changes
UnitySDK
New meta files
Cocos2d-xSDK specific changes
Cocos2d-xSDK
Android project should now compile.
Android project defaults to x86 processor, but can easily be switched to armeabi, or other processors
in Application.mk .
WindowsSDK specific changes
Compression has been disabled as it was having problems.
JavaScriptSDK specific changes
JavaScriptSDK
Overhauled – Not compatible with previous releases, so please beware!

150824
Date: 2015-08-23
API changes
Updated some descriptions for API-documentation.
GetUserInventoryResult contains new optional parameters: PlayFabId , CharacterId .
GetCharacterStatisticsResult contains new optional parameters: PlayFabId , CharacterId .
When calling GetTitleData return, all title data instead of none when no filter keys are provided.
Refactored code around Facebook login and payments to unify API calls to Facebook.
Added GetAllUsersCharacters API.
UnitySDK specific changes
UnitySDK
Error callback contains better information if you attempt to make API calls with no internet access.
WindowsSDK specific changes
Compiling for Android no longer throws errors (but doesn't work yet when executed).

150817 iOS
Date: 2015-08-16
API changes
Fixed issue with CloudScript admin APIs returning inappropriate error codes.
Added support for custom ID authentication.
Fixed server error when granting items that included a drop table that had been deleted before we added
drop table validation.
Internally rebuilt code around iTunes and Google Play receipt validation.
Improved handling of invalid JSON in API requests.
Fixed issue caused by stacking past Int32 max (now stacks are capped at Int32 max).
SDK specific changes
Initial release of versioned SDKs.

150810
Date: 2015-08-09
API changes
Added cross domain settings for APIs.
Added base for new title monitoring services.
Added Kongregate API key to title secret keys editor in Game Manager.
Updated SDK generator to account for interfaces and inheritance.
Fixed JSON upload/download of drop tables in Game Manager.
Added unit test coverage to documentation generator.
Added retry for iTunes receipt validation when a web error has occurred.
Added support for Facebook payments.
Added currency conversion service.

150727
Date: 2015-07-26
API changes
Improved random number generator used to generate IDs.
Added catch for Base64 decoding errors when validation Google Play receipts.

150720
Date: 2015-07-19
API changes
Added PayPal payment provider support for purchases.
Removed CatalogVersion from GetUserInventory API call.
Added Kongragate Authentication APIs.

150713
Date: 2015-07-12
API changes
Added audit log entries for terminating games and lobbies from Game Manager.
Fixed issue where the Store Index would not be updated when a Store was modified.
Added internal utility to migrate a studio across publishers.
Added switch to enable viewing beta features in doc site.
Updated retention report to generate calendar week cohorts.
Added PlayFab IDs to Top Spenders Report instead of just user names.
Fixed Game Manager audit log to show user's display name or email.
Added User Title Data editors to Game Manager.

150706
Date: 2015-07-05
API changes
Fixed errors on APIs that used string arrays, where the client passed in null or empty values for a list of
PlayFab IDs.

150629
Date: 2015-06-28
API changes
Added ability to flag APIs as Beta.
Fixed issue with stacking not always performing properly.
REST API overview
5/24/2022 • 2 minutes to read • Edit Online

Welcome to the PlayFab REST API reference. Here you will find reference material and gain insight into how our
APIs work. Each API reference is broken down into several different sections.

Endpoint
The endpoint is the HTTP URL that you can make API requests against. It is preceded with a REST method type
(eg. GET, POST). In addition, the titleId must be replaced with your game titleId.
Example:

POST https://[titleId].playfabapi.com/Client/LoginWithCustomID

Request Body
The request body is the object model that is sent as (JSON) to our API service. These models will contain
properties that need to be sent along with your API as the payload. Some properties will be flagged as
required , while others are optional .

Responses
The API service will either return a 200 OK with a JSON payload that can be deserialized as a model. In the
below example, Login API calls deserialize into a type of LoginResult.

If the response fails for any reason, a 400 Bad Request is received. This could mean the API service is returning
information about a bad request. Often, this could be missing parameters in your API call or a number of other
reasons. The ApiErrorWrapper object contains valuable information about the error including error codes, error
details and error messages from the server.

Security
Each API has some form of security that needs to be passed in the header of each request. See this section to
know what needs to be defined. Sometimes this is a session ticket from a login request or it could be your title
secret key if you are making server api requests.

Model Definitions
Each response from the API service can contain one or more Models in the response. These are located below
the ApiErrorWrapper and each model is represented in the same document as the API. Each model is also linked
in the response parent model. You can also visit the Definitions section in each API page to see a list of Models
supported by the API.
Event Model Definitions
The PlayStream Event Model reference contains the models of the automatically generated PlayStream event
types. Each event type has a set of properties that are included as part of event's data wherever it is sent.
Real-time notifications for Lobby and Matchmaking
APIs
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

NOTE
Using Lobby, Matchmaking, and real-time notifications directly with REST and SignalR APIs is significantly more complex
than using client SDKs such as the Lobby C++ SDK and Matchmaking C++ SDK, and should only be done if the SDKs
don't meet your needs.

The Lobby and Matchmaking services offer a real-time notifications feature, which enables individual game
clients to subscribe to receive notifications from these services. Game clients subscribe for notifications over a
persistent SignalR WebSocket connection. To learn more about the scenario as a whole, see the conceptual
documentation for Lobby and Matchmaking real-time notifications.
To use this feature, game clients will first need to implement a SignalR client that connects to the SignalR Hub
for real-time notifications. Once connected, the clients can subscribe to resources they would like to receive
notifications for.

See also
Real-time notifications SignalR Hub
Subscribing to resources
Real-time notifications SignalR Hub
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

NOTE
Using Lobby, Matchmaking, and real-time notifications directly with REST and SignalR APIs is significantly more complex
than using client SDKs such as the Lobby C++ SDK and Matchmaking C++ SDK, and should only be done if the SDKs
don't meet your needs.

The real-time notifications feature for Lobby and Matchmaking services works through a SignalR service, which
exposes a SignalR Hub. This SignalR Hub can be used by game clients to receive messages about resources they
subscribed to.

Connecting to the SignalR Hub


The first step in receiving real-time notifications is to create a SignalR client. The client can create a connection to
the SignalR Hub by instantiating a HubConnection with the following API: SignalR Negotiate REST API. This API
implements the Negotiate API described in the SignalR documentation.

NOTE
1. SignalR client implementations expect the URL to omit the /negotiate portion of this path (ex: HubConnection
should created to a URL that ends in ...playfabapi.com/pubsub ).
2. The auth headers required to call this API can be passed to the SignalR client via HttpConnectionOptions as seen on
this method.
3. The only encoding the hub currently supports is JSON encoding.

Implementing client methods to receive messages


See the SignalR Client documentation about implementing client methods that will be invoked to receive
messages. Clients should implement all of the methods listed in Client methods below.

Starting and ending a session by calling server methods


See the SignalR Client documentation about calling server methods to manage your session. For example, once
connected to the hub, you must call StartOrRecoverSession to receive a connection handle that you can use to
subscribe to resources. Similarly, once you're done with the session, call EndSession.

Subscribing to resources
Once a session has been started with StartOrRecoverSession, you can use the connection handle returned to
start subscribing to resources and receiving messages.
APIs
Client methods
NAME DESC RIP T IO N

ReceiveMessage Receive a notification message.

ReceiveSubscriptionChangeMessage Receive a SubscriptionChangeMessage to track current


subscriptions.

Server methods
NAME DESC RIP T IO N

StartOrRecoverSession Start or recover a session.

EndSession End the session.

Shared session methods

NAME DESC RIP T IO N

AddEntityToSession For scenarios where multiple entities are signed in to the


same device. Add an extra entity to the session, to receive
messages for multiple local entities on a shared session.

RemoveEntityFromSession Remove an entity from the session.

See also
Subscribing to resources
Real-time notifications for Lobby and Matchmaking APIs
Subscribing to resources
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

NOTE
Using Lobby, Matchmaking, and real-time notifications directly with REST and SignalR APIs is significantly more complex
than using client SDKs such as the Lobby C++ SDK and Matchmaking C++ SDK, and should only be done if the SDKs
don't meet your needs.

After the client connects to the SignalR Hub, and calls StartOrRecoverSession to receive a Connection Handle , it's
ready to subscribe to topics and receive messages. When subscribing to Lobby or Matchmaking resources, the
client will need to provide the Connection Handle that they received when starting the session. For more
information about starting and managing a session, see the SignalR Hub overview.
To manage resource subscriptions with the services that publish notifications, see:

SERVIC E SUB SC RIP T IO N A P I UN SUB SC RIP T IO N A P I

Lobby service SubscribeToLobbyResource UnsubscribeFromLobbyResource

Matchmaking service SubscribeToMatchmakingResource UnsubscribeFromMatchmakingResourc


e

See also
Real-time notifications SignalR Hub
Real-time notifications for Lobby and Matchmaking APIs
ReceiveMessage
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

NOTE
Using Lobby, Matchmaking, and real-time notifications directly with REST and SignalR APIs is significantly more complex
than using client SDKs such as the Lobby C++ SDK and Matchmaking C++ SDK, and should only be done if the SDKs
don't meet your needs.

Receives messages from real-time notifications subscriptions.

ReceiveMessage(Message message)

TIP
This is a SignalR client method. See documentation on exposing client methods in a SignalR client, which will be invoked
by the server.

Parameters
Message

See also
Type Message
Client method ReceiveSubscriptionChangeMessage
Real-time notifications SignalR Hub
Real-time notifications for Lobby and Matchmaking APIs
ReceiveSubscriptionChangeMessage
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

NOTE
Using Lobby, Matchmaking, and real-time notifications directly with REST and SignalR APIs is significantly more complex
than using client SDKs such as the Lobby C++ SDK and Matchmaking C++ SDK, and should only be done if the SDKs
don't meet your needs.

Receives SubscriptionChangeMessages, so the client will know when its subscription status changes. This
message indicates that a request to subscribe or unsubscribe has finished processing.

ReceiveSubscriptionChangeMessage(SubscriptionChangeMessage subscriptionChangeMessage)

TIP
This is a SignalR client method. See documentation on exposing client methods in a SignalR client, which will be invoked
by the server.

Parameters
SubscriptionChangeMessage

See also
Type SubscriptionChangeMessage
Client method ReceiveMessage
Real-time notifications SignalR Hub
Real-time notifications for Lobby and Matchmaking APIs
AddEntityToSession
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

NOTE
Using Lobby, Matchmaking, and real-time notifications directly with REST and SignalR APIs is significantly more complex
than using client SDKs such as the Lobby C++ SDK and Matchmaking C++ SDK, and should only be done if the SDKs
don't meet your needs.

For scenarios where multiple entities are signed in to the same device. Add an additional entity to the session,
other than the entity that started the session. This will allow the client to receive messages for multiple local
entities on a shared session.

SharedSessionResponse AddEntityToSession(SharedSessionRequest request)

TIP
This is a SignalR server method. See documentation on calling server methods from a SignalR client.

Parameters
SharedSessionRequest

Return value
SharedSessionResponse

See also
Server method RemoveEntityFromSession.
Real-time notifications SignalR Hub
Real-time notifications for Lobby and Matchmaking APIs
EndSession
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

NOTE
Using Lobby, Matchmaking, and real-time notifications directly with REST and SignalR APIs is significantly more complex
than using client SDKs such as the Lobby C++ SDK and Matchmaking C++ SDK, and should only be done if the SDKs
don't meet your needs.

End the session.

EndSessionResponse EndSession(EndSessionRequest request)

TIP
This is a SignalR server method. See documentation on calling server methods from a SignalR client.

Parameters
EndSessionRequest

Return value
EndSessionResponse

See also
Server method StartOrRecoverSession.
Real-time notifications SignalR Hub
Real-time notifications for Lobby and Matchmaking APIs
RemoveEntityFromSession
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

NOTE
Using Lobby, Matchmaking, and real-time notifications directly with REST and SignalR APIs is significantly more complex
than using client SDKs such as the Lobby C++ SDK and Matchmaking C++ SDK, and should only be done if the SDKs
don't meet your needs.

Remove an additional entity that was added to the session with AddEntityToSession.

SharedSessionResponse RemoveEntityFromSession(SharedSessionRequest request)

TIP
This is a SignalR server method. See documentation on calling server methods from a SignalR client.

Parameters
SharedSessionRequest

Return value
SharedSessionResponse

See also
Server method AddEntityToSession
Real-time notifications SignalR Hub
Real-time notifications for Lobby and Matchmaking APIs
StartOrRecoverSession
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

NOTE
Using Lobby, Matchmaking, and real-time notifications directly with REST and SignalR APIs is significantly more complex
than using client SDKs such as the Lobby C++ SDK and Matchmaking C++ SDK, and should only be done if the SDKs
don't meet your needs.

Starts a session.
The client must call this method to start the session and obtain the Connection Handle representing it. The client
must store this Connection Handle to later use to create subscriptions for the session.

StartOrRecoverSessionResponse StartOrRecoverSession(StartOrRecoverSessionRequest request)

TIP
This is a SignalR server method. See documentation on calling server methods from a SignalR client.

Parameters
StartOrRecoverSessionRequest

Return value
StartOrRecoverSessionResponse

See also
Server method EndSession
Real-time notifications SignalR Hub
Real-time notifications for Lobby and Matchmaking APIs
EndSessionRequest
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

NOTE
Using Lobby, Matchmaking, and real-time notifications directly with REST and SignalR APIs is significantly more complex
than using client SDKs such as the Lobby C++ SDK and Matchmaking C++ SDK, and should only be done if the SDKs
don't meet your needs.

{
"traceParent": "00-84678fd69ae13e41fce1333289bcf482-22d157fb94ea4827-01"
}

Members
traceParent string
A valid W3C TraceContext TraceParent Header.
Example: 00-84678fd69ae13e41fce1333289bcf482-22d157fb94ea4827-01

See also
Type EndSessionResponse
Server method EndSession
Real-time notifications SignalR Hub
Real-time notifications for Lobby and Matchmaking APIs
EndSessionResponse
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

NOTE
Using Lobby, Matchmaking, and real-time notifications directly with REST and SignalR APIs is significantly more complex
than using client SDKs such as the Lobby C++ SDK and Matchmaking C++ SDK, and should only be done if the SDKs
don't meet your needs.

{
"status": "Success",
"traceId": "00-84678fd69ae13e41fce1333289bcf482-22d157fb94ea4827-01"
}

Members
status string
The status of the response. See all possible ResponseStatus values here.
Example: Success

traceId string
A W3C TraceContext trace-id. The client should log this field so it can be included if you need to send a bug
report to the PlayFab team.
Example: 4bf92f3577b34da6a3ce929d0e0e4736

See also
Type EndSessionRequest
Server method EndSession
Real-time notifications SignalR Hub
Real-time notifications for Lobby and Matchmaking APIs
Message
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

NOTE
Using Lobby, Matchmaking, and real-time notifications directly with REST and SignalR APIs is significantly more complex
than using client SDKs such as the Lobby C++ SDK and Matchmaking C++ SDK, and should only be done if the SDKs
don't meet your needs.

{
"topic": "Opaque~Topic~String~6183258",
"payload":
"eyJsb2JieUlkIjoiODEyNDZmY2ItMWVmNy00ZmU1LTliYzctZTg3MjBiNmFjNWIxIiwibG9iYnlDaGFuZ2VzIjpbeyJjaGFuZ2VOdW1iZXI
iOjEsIm1lbWJlclRvTWVyZ2UiOnsibWVtYmVyRW50aXR5Ijp7IlR5cGUiOiJ0aXRsZV9wbGF5ZXJfYWNjb3VudCIsIklkIjoiOTgxRDU5MTc
wRTI4NEE3MiJ9fX1dfQ==",
"traceId": "4bf92f3577b34da6a3ce929d0e0e4736"
}

Members
topic string
A topic string, matching the topic string returned when subscribing to resources. This field allows the client to
keep track of which messages are for which resources they subscribed to.
Example: Opaque~Topic~String~6183258

payload string
The payload of the message.
Example:
eyJsb2JieUlkIjoiODEyNDZmY2ItMWVmNy00ZmU1LTliYzctZTg3MjBiNmFjNWIxIiwibG9iYnlDaGFuZ2VzIjpbeyJjaGFuZ2VOdW1iZXIiOjEsIm1lbWJlclRvTWVyZ2UiOnsibWVtYmVyRW50aXR5Ijp7IlR5cGUiOiJ0aX

traceId string
A W3C TraceContext trace-id. The client should log this field so it can be included if you need to send a bug
report to the PlayFab team.
Example: 4bf92f3577b34da6a3ce929d0e0e4736

See also
Client method ReceiveMessage
Real-time notifications SignalR Hub
Real-time notifications for Lobby and Matchmaking APIs
Response Status
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

NOTE
Using Lobby, Matchmaking, and real-time notifications directly with REST and SignalR APIs is significantly more complex
than using client SDKs such as the Lobby C++ SDK and Matchmaking C++ SDK, and should only be done if the SDKs
don't meet your needs.

Possible values for the status member of SignalR server method responses.

Values
VA L UE DESC RIP T IO N

Success

InternalServerError An error occurred in the service. The request can be retried a


few times with exponential backoff.

SharedSessionEntityLimitExceeded An AddEntityToSession request attempted to add more than


8 entities to the connection.

UnsupportedEntityType An AddEntityToSession request attempted to add an entity


type other than title_player_account to the session.

InvalidRequest Fields in the request were invalid.

Unavailable The service is temporarily unavailable. The request can be


retried a few times with exponential backoff.

TooManyRequests The individual client or title all-up has exceeded its request
rate limit, and the request was throttled. The request can be
retried a few times with exponential backoff.

See also
Type EndSessionResponse
Type SharedSessionResponse
Type StartOrRecoverSessionResponse
Real-time notifications SignalR Hub
Real-time notifications for Lobby and Matchmaking APIs
SharedSessionRequest
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

NOTE
Using Lobby, Matchmaking, and real-time notifications directly with REST and SignalR APIs is significantly more complex
than using client SDKs such as the Lobby C++ SDK and Matchmaking C++ SDK, and should only be done if the SDKs
don't meet your needs.

{
"entityType": "title_player_account",
"entityId": "6C6B908A2B5B9A4",
"traceParent": "00-84678fd69ae13e41fce1333289bcf482-22d157fb94ea4827-01"
}

Members
entityType string
The type of the entity to add to the session. Currently we only accept title_player_account .
Example: title_player_account

entityId string
The ID of the entity to add to the session.
Example: 6C6B908A2B5B9A4

traceParent string
A valid W3C TraceContext TraceParent Header.
Example: 00-84678fd69ae13e41fce1333289bcf482-22d157fb94ea4827-01

See also
Type SharedSessionResponse
Server method AddEntityToSession
Server method RemoveEntityFromSession
Real-time notifications SignalR Hub
Real-time notifications for Lobby and Matchmaking APIs
SharedSessionResponse
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

NOTE
Using Lobby, Matchmaking, and real-time notifications directly with REST and SignalR APIs is significantly more complex
than using client SDKs such as the Lobby C++ SDK and Matchmaking C++ SDK, and should only be done if the SDKs
don't meet your needs.

{
"entityCount": "2",
"status": "Success",
"traceId": "4bf92f3577b34da6a3ce929d0e0e4736"
}

Members
entityCount number optional
The number of entities currently in the shared session. This number can't exceed 8 .
Example: 2

status string
The status of the response. See all possible ResponseStatus values here.
Example: Success

traceId string
A W3C TraceContext trace-id. The client should log this field so it can be included if you need to send a bug
report to the PlayFab team.
Example: 4bf92f3577b34da6a3ce929d0e0e4736

See also
Type SharedSessionRequest
Server method AddEntityToSession
Server method RemoveEntityFromSession
Real-time notifications SignalR Hub
Real-time notifications for Lobby and Matchmaking APIs
StartOrRecoverSessionRequest
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

NOTE
Using Lobby, Matchmaking, and real-time notifications directly with REST and SignalR APIs is significantly more complex
than using client SDKs such as the Lobby C++ SDK and Matchmaking C++ SDK, and should only be done if the SDKs
don't meet your needs.

{
"oldConnectionHandle": "1.Y2VudHJhbC11c35sb2NhbGhvc3R+QkxVV1pYSEwwZkF0b1o5WUR2MV9vQQ==",
"traceParent": "00-84678fd69ae13e41fce1333289bcf482-22d157fb94ea4827-01"
}

Members
oldConnectionHandle string optional
If recovering a session due to unexpected disconnection, subscriptions can be recovered by providing the
newConnectionHandle from the last session's StartOrRecoverSessionResponse.

Example: 1.Y2VudHJhbC11c35sb2NhbGhvc3R+QkxVV1pYSEwwZkF0b1o5WUR2MV9vQQ==

traceParent string
A valid W3C TraceContext TraceParent Header.
Example: 00-84678fd69ae13e41fce1333289bcf482-22d157fb94ea4827-01

See also
Type StartOrRecoverSessionResponse
Server method StartOrRecoverSession
Real-time notifications SignalR Hub
Real-time notifications for Lobby and Matchmaking APIs
StartOrRecoverSessionResponse
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

NOTE
Using Lobby, Matchmaking, and real-time notifications directly with REST and SignalR APIs is significantly more complex
than using client SDKs such as the Lobby C++ SDK and Matchmaking C++ SDK, and should only be done if the SDKs
don't meet your needs.

{
"newConnectionHandle": "1.Y2VudHJhbC11c35sb2NhbGhvc3R+QkxVV1pYSEwwZkF0b1o5WUR2MV9vQQ==",
"recoveredTopics": ["Opaque~Topic~String~6183258", "Another~Opaque~Topic~String~843156"],
"status": "Success",
"traceId": "4bf92f3577b34da6a3ce929d0e0e4736"
}

Members
newConnectionHandle string
An opaque string Connection Handle .
The client doesn't need to concern itself with the contents of the connection handle. The client must acquire it
when starting a new session and pass it in requests to subscribe to resources.
If there's an unexpected disconnection with the SignalR server, subscriptions can be recovered on a new
connection by providing it as the oldConnectionHandle when calling StartOrRecoverSessionRequest.
Example: 1.Y2VudHJhbC11c35sb2NhbGhvc3R+QkxVV1pYSEwwZkF0b1o5WUR2MV9vQQ==

recoveredTopics string[] optional


A list of topic strings, matching the topic strings returned when subscribing to resources. This list only contains
values if a session was recovered from an old Connection Handle and subscriptions were found to recover. It's
possible that some subscriptions that are expected here will not be recovered. If there are any missing
subscriptions the client should resubscribe to those resources.
Example: ["Opaque~Topic~String~6183258", "Another~Opaque~Topic~String~843156"]

status string
The status of the response. See all possible ResponseStatus values here.
Example: Success

traceId string
A W3C TraceContext trace-id. The client should log this field so it can be included if you need to send a bug
report to the PlayFab team.
Example: 4bf92f3577b34da6a3ce929d0e0e4736

See also
Type StartOrRecoverSessionRequest
Server method StartOrRecoverSession
Real-time notifications SignalR Hub
Real-time notifications for Lobby and Matchmaking APIs
SubscriptionChangeMessage
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

NOTE
Using Lobby, Matchmaking, and real-time notifications directly with REST and SignalR APIs is significantly more complex
than using client SDKs such as the Lobby C++ SDK and Matchmaking C++ SDK, and should only be done if the SDKs
don't meet your needs.

{
"entityType": "title_player_account",
"entityId": "6C6B908A2B5B9A4",
"topic": "Opaque~Topic~String~6183258",
"status": "SubscribeSuccess",
"unsubscribeReason": "ResourceOwningServiceDefinedReason",
"traceId": "4bf92f3577b34da6a3ce929d0e0e4736"
}

Members
entityType string
The type of the entity whose subscription changed. Clients may only care about this field if they added multiple
entities to the same session.
Example: title_player_account

entityId string
The ID of the entity whose subscription changed. Clients may only care about this field if they added multiple
entities to the same session.
Example: 6C6B908A2B5B9A4

topic string
A topic string, matching the topic string returned when subscribing to resources. This field allows the client to
keep track of which messages are for which resources they subscribed to.
Example: Opaque~Topic~String~6183258

status string
The status of the subscription change.
P O SSIB L E VA L UES DESC RIP T IO N

SubscribeSuccess The subscription succeeded. The client can assume they'll


receive all messages for the topic from this point on.

SubscribeFailure The subscription failed. The client can retry subscribing to


the resource.

AlreadySubscribed The client is already subscribed to the resource it attempted


to subscribe to again.

UnsubscribeSuccess The unsubscription succeeded.

UnsubscribeFailure The unsubscription failed. The client can retry unsubscribing


from the resource.

NoSubscription The client isn't subscribed to the resource it attempted to


unsubscribe from.

unsubscribeReason string optional


A reason for unsubscription, that can be optionally provided by the service handling the unsubscribe request.
Example: ResourceOwningServiceDefinedReason

traceId string
A W3C TraceContext trace-id. The client should log this field so it can be included if you need to send a bug
report to the PlayFab team.
Example: 4bf92f3577b34da6a3ce929d0e0e4736

See also
Client method ReceiveSubscriptionChangeMessage
Real-time notifications SignalR Hub
Real-time notifications for Lobby and Matchmaking APIs
Party C/C++ API overview
5/24/2022 • 5 minutes to read • Edit Online

Classes
C L A SS DESC RIP T IO N

PartyAudioManipulationSinkStream The management class for submitting audio to an audio sink


stream.

PartyAudioManipulationSourceStream The management class for obtaining audio from an audio


source stream.

PartyChatControl The management class for chat operations.

PartyDevice Represents a device across networks.

PartyEndpoint Represents an endpoint in a network.

PartyInvitation Represents an invitation used to authenticate a user into a


network.

PartyLocalChatControl The management class for chat operations related to the


local device.

PartyLocalDevice Represents the local device.

PartyLocalEndpoint Represents a local endpoint.

PartyLocalUser Represents a local user.

PartyManager The primary management class for interacting with the Party
library.

PartyNetwork Represents a network.

PartyTextToSpeechProfile Represents the voice profile used to synthesize speech.

Callbacks
C ALLBAC K DESC RIP T IO N

PartyAllocateMemoryCallback A callback invoked every time a new memory buffer must be


dynamically allocated by the Party library.

PartyFreeMemoryCallback A callback invoked every time a previously allocated memory


buffer is no longer needed by the Party library and can be
freed.
C ALLBAC K DESC RIP T IO N

PartyProfilingMethodEntranceCallback A callback invoked every time the Party library enters an


instrumented method.

PartyProfilingMethodExitCallback A callback invoked every time the Party library is about to


exit an instrumented method.

Structures
ST RUC T URE DESC RIP T IO N

PartyAudioFormat The format information needed to interpret Party audio


data.

PartyAudioManipulationSinkStreamConfiguration The configuration information needed to set up an audio


sink stream.

PartyAudioManipulationSourceStreamConfiguration The configuration information needed to set up an audio


source stream.

PartyDataBuffer A data buffer.

PartyInvitationConfiguration Invitation configuration data.

PartyLocalUdpSocketBindAddressConfiguration The configuration used by the Party library to bind to a UDP


socket.

PartyMutableDataBuffer A data buffer that can be modified by the app.

PartyNetworkConfiguration Network configuration data.

PartyNetworkDescriptor A descriptor containing the data required for a device to


connect to a network.

PartyProfilingMethodEntranceEventData Information specific to the MethodEntrance type of profiling


event.

PartyProfilingMethodExitEventData Information specific to the MethodExit type of profiling


event.

PartyRegion Represents a Party library region.

PartySendMessageQueuingConfiguration Optional configuration parameters for modifying local


queuing behavior when sending a message.

PartyTranslation A translation.

State changes
STAT E C H A N GE DESC RIP T IO N
STAT E C H A N GE DESC RIP T IO N

PartyAuthenticateLocalUserCompletedStateChange Information specific to the AuthenticateLocalUserCompleted


type of state change.

PartyChatControlCreatedStateChange Information specific to the ChatControlCreated type of state


change.

PartyChatControlDestroyedStateChange Information specific to the ChatControlDestroyed type of


state change.

PartyChatControlJoinedNetworkStateChange Information specific to the ChatControlJoinedNetwork type


of state change.

PartyChatControlLeftNetworkStateChange Information specific to the ChatControlLeftNetwork type of


state change.

PartyChatTextReceivedStateChange Information specific to the ChatTextReceived type of state


change.

PartyConfigureAudioManipulationCaptureStreamCompleted Information specific to the


StateChange ConfigureAudioManipulationCaptureStreamCompleted type
of state change.

PartyConfigureAudioManipulationRenderStreamCompletedSt Information specific to the


ateChange ConfigureAudioManipulationRenderStreamCompleted type
of state change.

PartyConfigureAudioManipulationVoiceStreamCompletedSta Information specific to the


teChange ConfigureAudioManipulationVoiceStreamCompleted type of
state change.

PartyConnectChatControlCompletedStateChange Information specific to the ConnectChatControlCompleted


type of state change.

PartyConnectToNetworkCompletedStateChange Information specific to the ConnectToNetworkCompleted


type of state change.

PartyCreateChatControlCompletedStateChange Information specific to the CreateChatControlCompleted


type of state change.

PartyCreateEndpointCompletedStateChange Information specific to the CreateEndpointCompleted type


of state change.

PartyCreateInvitationCompletedStateChange Information specific to the CreateInvitationCompleted type


of state change.

PartyCreateNewNetworkCompletedStateChange Information specific to the CreateNewNetworkCompleted


type of state change.

PartyDataBuffersReturnedStateChange Information specific to the DataBuffersReturned type of state


change.

PartyDestroyChatControlCompletedStateChange Information specific to the DestroyChatControlCompleted


type of state change.
STAT E C H A N GE DESC RIP T IO N

PartyDestroyEndpointCompletedStateChange Information specific to the DestroyEndpointCompleted type


of state change.

PartyDestroyLocalUserCompletedStateChange Information specific to the DestroyLocalUserCompleted type


of state change.

PartyDisconnectChatControlCompletedStateChange Information specific to the


DisconnectChatControlCompleted type of state change.

PartyEndpointCreatedStateChange Information specific to the EndpointCreated type of state


change.

PartyEndpointDestroyedStateChange Information specific to the EndpointDestroyed type of state


change.

PartyEndpointMessageReceivedStateChange Information specific to the EndpointMessageReceived type of


state change.

PartyInvitationCreatedStateChange Information specific to the InvitationCreated type of state


change.

PartyInvitationDestroyedStateChange Information specific to the InvitationDestroyed type of state


change.

PartyLeaveNetworkCompletedStateChange Information specific to the LeaveNetworkCompleted type of


state change.

PartyLocalChatAudioInputChangedStateChange Information specific to the LocalChatAudioInputChanged


type of state change.

PartyLocalChatAudioOutputChangedStateChange Information specific to the LocalChatAudioOutputChanged


type of state change.

PartyLocalUserRemovedStateChange Information specific to the LocalUserRemoved type of state


change.

PartyNetworkConfigurationMadeAvailableStateChange Information specific to the


NetworkConfigurationMadeAvailable type of state change.

PartyNetworkDescriptorChangedStateChange Information specific to the NetworkDescriptorChanged type


of state change.

PartyNetworkDestroyedStateChange Information specific to the NetworkDestroyed type of state


change.

PartyPopulateAvailableTextToSpeechProfilesCompletedStateC Information specific to the


hange PopulateAvailableTextToSpeechProfilesCompleted type of
state change.

PartyRegionsChangedStateChange Information specific to the RegionsChanged type of state


change.

PartyRemoteDeviceCreatedStateChange Information specific to the RemoteDeviceCreated type of


state change.
STAT E C H A N GE DESC RIP T IO N

PartyRemoteDeviceDestroyedStateChange Information specific to the RemoteDeviceDestroyed type of


state change.

PartyRemoteDeviceJoinedNetworkStateChange Information specific to the RemoteDeviceJoinedNetwork type


of state change.

PartyRemoteDeviceLeftNetworkStateChange Information specific to the RemoteDeviceLeftNetwork type of


state change.

PartyRemoveLocalUserCompletedStateChange Information specific to the RemoveLocalUserCompleted type


of state change.

PartyRevokeInvitationCompletedStateChange Information specific to the RevokeInvitationCompleted type


of state change.

PartySetChatAudioInputCompletedStateChange Information specific to the SetChatAudioInputCompleted


type of state change.

PartySetChatAudioOutputCompletedStateChange Information specific to the SetChatAudioOutputCompleted


type of state change.

PartySetTextChatOptionsCompletedStateChange Information specific to the


PartySetTextChatOptionsCompleted type of state change.

PartySetTextToSpeechProfileCompletedStateChange Information specific to the SetTextToSpeechProfileCompleted


type of state change.

PartySetTranscriptionOptionsCompletedStateChange Information specific to the


SetTranscriptionOptionsCompleted type of state change.

PartyStateChange A generic, base structure representation of an event or


change in state.

PartySynthesizeTextToSpeechCompletedStateChange Information specific to the


SynthesizeTextToSpeechCompleted type of state change.

PartyVoiceChatTranscriptionReceivedStateChange Information specific to the VoiceChatTranscriptionReceived


type of state change.

Enumerations
EN UM ERAT IO N DESC RIP T IO N

PartyAudioDeviceSelectionType Options for selecting audio devices

PartyAudioInputState States of an audio input associated with a local chat control.

PartyAudioOutputState States of an audio output associated with a local chat


control.

PartyAudioSampleType Types of Party audio samples.


EN UM ERAT IO N DESC RIP T IO N

PartyAudioSourceType Types of Party audio sources.

PartyChatControlChatIndicator Audio states for a target chat control in relation to a local


chat control.

PartyChatPermissionOptions Options for defining the communication relationship


between two chat controls.

PartyChatTextReceivedOptions Flags describing the received text message in


PartyChatTextReceivedStateChange.

PartyDestroyedReason Reasons an object might be destroyed.

PartyDeviceConnectionType The type of connection used for transmitting endpoint


message or chat data to a device.

PartyDirectPeerConnectivityOptions Flags controlling the attempted use of direct peer-to-peer


connectivity among devices in a network.

PartyEndpointStatistic Types of statistics that can be retrieved for an endpoint.

PartyGender Genders for text to speech profiles.

PartyInvitationRevocability Options for who may revoke an invitation.

PartyLocalChatControlChatIndicator Audio states for a local chat control.

PartyLocalUdpSocketBindAddressOptions Additional options to control how the Party library binds to


the UDP socket specified by the
PartyLocalUdpSocketBindAddressConfiguration structure.

PartyLocalUserRemovedReason Reasons for removing a local user from a network.

PartyMessageReceivedOptions Flags describing how a message was received.

PartyNetworkStatistic Types of statistics that can be retrieved for a network.

PartyOption Additional options that can be set to fine-tune Party library


functionality.

PartySendMessageOptions Options for controlling how a message is sent.

PartyStateChangeResult Results for operations that generate state changes.

PartyStateChangeType The types of state changes that can occur.

PartySynthesizeTextToSpeechType Types of text-to-speech operations.

PartyTextChatFilterLevel The level of filtering that will apply to incoming text chat
when text moderation is enabled with
PartyLocalChatControl::SetTextChatOptions.
EN UM ERAT IO N DESC RIP T IO N

PartyTextChatOptions Text chat options.

PartyThreadId High-level categorization of internal processing tasks.

PartyTranslationReceivedOptions Flags describing how a translation was received.

PartyVoiceChatTranscriptionOptions Voice chat transcription options.

PartyVoiceChatTranscriptionPhraseType Types of transcription phrases.

PartyWorkMode Configuration modes representing how the Party library will


manage an internal processing task.
PartyAudioManipulationSinkStream
5/24/2022 • 2 minutes to read • Edit Online

The management class for submitting audio to an audio sink stream.

Syntax
class PartyAudioManipulationSinkStream

Public Methods
NAME DESC RIP T IO N

GetConfiguration Retrieves the stream configuration.

GetFormat Retrieves the format of the buffers that will be submitted to


PartyAudioManipulationSinkStream::SubmitBuffer().

SubmitBuffer Submits audio to be processed by this sink. Depending on


the type of sink, this audio may be transmitted to other chat
controls or rendered to the audio output.

GetCustomContext Retrieves the app's private, custom pointer-sized context


value previously associated with this stream object.

SetCustomContext Configures an optional, custom pointer-sized context value


with this stream object.

Requirements
Header : Party.h

See also
Party members
PartyAudioManipulationSinkStream::GetConfiguration
5/24/2022 • 2 minutes to read • Edit Online

Retrieves the stream configuration.

Syntax
PartyError GetConfiguration(
PartyAudioManipulationSinkStreamConfiguration* configuration
)

Parameters
configuration PartyAudioManipulationSinkStreamConfiguration*
output
The stream configuration.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
The stream configuration matches the configuration provided to the configuration method used to create this
stream.

Requirements
Header : Party.h

See also
PartyAudioManipulationSinkStream
PartyLocalChatControl::ConfigureAudioManipulationCaptureStream
PartyLocalChatControl::ConfigureAudioManipulationRenderStream
PartyAudioManipulationSinkStream::GetFormat
5/24/2022 • 2 minutes to read • Edit Online

Retrieves the format of the buffers that will be submitted to PartyAudioManipulationSinkStream::SubmitBuffer().

Syntax
PartyError GetFormat(
PartyAudioFormat* format
)

Parameters
format PartyAudioFormat*
output
The format of the buffers that will be submitted to PartyAudioManipulationSinkStream::SubmitBuffer().
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
If a format is specified in the configuration provided by PartyAudioManipulationSinkStream::GetConfiguration(),
this format will match. Otherwise, this format will be the most efficient format automatically selected by the
library.

Requirements
Header : Party.h

See also
PartyAudioManipulationSinkStream
PartyLocalChatControl::ConfigureAudioManipulationCaptureStream
PartyLocalChatControl::ConfigureAudioManipulationRenderStream
PartyAudioManipulationSinkStream::SubmitBuffer
PartyAudioManipulationSinkStream::GetConfiguration
PartyAudioManipulationSinkStream::SubmitBuffer
5/24/2022 • 2 minutes to read • Edit Online

Submits audio to be processed by this sink. Depending on the type of sink, this audio may be transmitted to
other chat controls or rendered to the audio output.

Syntax
PartyError SubmitBuffer(
const PartyDataBuffer* buffer
)

Parameters
buffer PartyDataBuffer*

The audio buffer. Typically this audio buffer is generated by retrieving the next buffer available from each
incoming source stream, and then processing and mixing each buffer based on game logic. This buffer must
have the format format specified by PartyAudioManipulationSinkStream::GetFormat().
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
Every 40ms, the next 40 ms of audio from this stream will be processed. To prevent audio hiccups, buffers for
audio that should be heard continuously should be submitted to this stream at a constant rate.

The buffer is copied to an allocated buffer before PartyAudioManipulationSinkStream::SubmitBuffer() returns


and can be immediately freed afterwards.

When applying chat permissions and determining which chat controls should receive audio, audio submitted to
a capture sink via this method is treated as microphone audio.

Requirements
Header : Party.h

See also
PartyAudioManipulationSinkStream
PartyChatPermissionOptions
PartyAudioManipulationSinkStream::GetCustomContext
5/24/2022 • 2 minutes to read • Edit Online

Retrieves the app's private, custom pointer-sized context value previously associated with this stream object.

Syntax
PartyError GetCustomContext(
void** customContext
)

Parameters
customContext void**
output, may return nullptr
The output custom context.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
If no custom context has been set yet, the value pointed to by customContext is set to nullptr.

Requirements
Header : Party.h

See also
PartyAudioManipulationSinkStream
PartyAudioManipulationSinkStream::SetCustomContext
PartyAudioManipulationSinkStream::SetCustomContext
5/24/2022 • 2 minutes to read • Edit Online

Configures an optional, custom pointer-sized context value with this stream object.

Syntax
PartyError SetCustomContext(
void* customContext
)

Parameters
customContext void*
optional
An arbitrary, pointer-sized value to store with the network object.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
The custom context is typically used as a "shortcut" that simplifies accessing local, title-specific memory
associated with the network without requiring a mapping lookup. The value is retrieved using the
GetCustomContext() method.

Any configured value is treated as opaque by the library, and is only valid on the local device; it is not
transmitted over the network.

Requirements
Header : Party.h

See also
PartyAudioManipulationSinkStream
PartyAudioManipulationSinkStream::GetCustomContext
PartyAudioManipulationSourceStream
5/24/2022 • 2 minutes to read • Edit Online

The management class for obtaining audio from an audio source stream.

Syntax
class PartyAudioManipulationSourceStream

Public Methods
NAME DESC RIP T IO N

GetConfiguration Retrieves the stream configuration.

GetFormat Retrieves the format of the buffers that will be provided by


PartyAudioManipulationSourceStream::GetNextBuffer().

GetAvailableBufferCount Retrieves the total number of buffers available to retrieve


from this stream via
PartyAudioManipulationSourceStream::GetNextBuffer().

GetNextBuffer Gets the next buffer available in the stream.

ReturnBuffer Tells the library it can reclaim memory associated with this
buffer.

GetCustomContext Retrieves the app's private, custom pointer-sized context


value previously associated with this stream object.

SetCustomContext Configures an optional, custom pointer-sized context value


with this stream object.

Requirements
Header : Party.h

See also
Party members
PartyAudioManipulationSourceStream::GetConfiguration
5/24/2022 • 2 minutes to read • Edit Online

Retrieves the stream configuration.

Syntax
PartyError GetConfiguration(
PartyAudioManipulationSourceStreamConfiguration* configuration
)

Parameters
configuration PartyAudioManipulationSourceStreamConfiguration*
output
The stream configuration.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
The stream configuration matches the configuration provided to the call to
PartyChatControl::ConfigureAudioManipulationVoiceStream() used to create this stream.

Requirements
Header : Party.h

See also
PartyAudioManipulationSourceStream
PartyChatControl::ConfigureAudioManipulationVoiceStream
PartyAudioManipulationSourceStream::GetFormat
5/24/2022 • 2 minutes to read • Edit Online

Retrieves the format of the buffers that will be provided by


PartyAudioManipulationSourceStream::GetNextBuffer().

Syntax
PartyError GetFormat(
PartyAudioFormat* format
)

Parameters
format PartyAudioFormat*
output
The format of the buffers that will be provided by PartyAudioManipulationSourceStream::GetNextBuffer().
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
If a format is specified in the configuration provided by
PartyAudioManipulationSourceStream::GetConfiguration(), this format will match. Otherwise, this format will be
the most efficient format automatically selected by the library.

Requirements
Header : Party.h

See also
PartyAudioManipulationSourceStream
PartyChatControl::ConfigureAudioManipulationVoiceStream
PartyAudioManipulationSourceStream::GetNextBuffer
PartyAudioManipulationSourceStream::GetConfiguration
PartyAudioManipulationSourceStream::GetAvailableBufferCount
5/24/2022 • 2 minutes to read • Edit Online

Retrieves the total number of buffers available to retrieve from this stream via
PartyAudioManipulationSourceStream::GetNextBuffer().

Syntax
PartyError GetAvailableBufferCount(
uint32_t* count
)

Parameters
count uint32_t*
output
The output count of available buffers.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
This can be useful if the caller prefers to send audio through their pipeline in batches of buffers. Because this
buffer count is limited by the max audio queue size specified via
PartyChatControl::ConfigureAudioManipulationVoiceStream(), callers should give their audio processing
pipeline ample time to process the buffers and return them to
PartyAudioManipulationSourceStream::ReturnBuffer() to prevent dropped audio.

Requirements
Header : Party.h

See also
PartyAudioManipulationSourceStream
PartyAudioManipulationSourceStream::GetNextBuffer
5/24/2022 • 2 minutes to read • Edit Online

Gets the next buffer available in the stream.

Syntax
PartyError GetNextBuffer(
PartyMutableDataBuffer* buffer
)

Parameters
buffer PartyMutableDataBuffer*
output
The output buffer. If no buffer is available, the PartyMutableDataBuffer's bufferByteCount field will be 0 and its
buffer field will be nullptr.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
When voice activity is detected, a new buffer will be available every 40 ms. Otherwise, no buffers will be
available. Buffers retrieved by this method must be returned to the library via
PartyAudioManipulationSourceStream::ReturnBuffer() when they are done being used.

The total number of buffers instantaneously available can be retrieved via


PartyAudioManipulationSourceStream::GetAvailableBufferCount(). Multiple buffers can be retrieved in
succession before any are returned.

Each buffer will be in the format specified by PartyAudioManipulationSourceStream::GetFormat().

A mutable data buffer is provided so that the app can optionally modify the audio in place.

Requirements
Header : Party.h

See also
PartyAudioManipulationSourceStream
PartyAudioManipulationSourceStream::GetFormat
PartyAudioManipulationSourceStream::ReturnBuffer
PartyAudioManipulationSourceStream::ReturnBuffer
5/24/2022 • 2 minutes to read • Edit Online

Tells the library it can reclaim memory associated with this buffer.

Syntax
PartyError ReturnBuffer(
void* buffer
)

Parameters
buffer void*
input not valid afterwards
The buffer to return, which is the buffer field of a PartyDataBuffer previously retrieved from this source stream
PartyAudioManipulationSourceStream::GetNextBuffer().
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Requirements
Header : Party.h

See also
PartyAudioManipulationSourceStream
PartyAudioManipulationSourceStream::GetNextBuffer
PartyAudioManipulationSourceStream::GetCustomContext
5/24/2022 • 2 minutes to read • Edit Online

Retrieves the app's private, custom pointer-sized context value previously associated with this stream object.

Syntax
PartyError GetCustomContext(
void** customContext
)

Parameters
customContext void**
output, may return nullptr
The output custom context.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
If no custom context has been set yet, the value pointed to by customContext is set to nullptr.

Requirements
Header : Party.h

See also
PartyAudioManipulationSourceStream
PartyAudioManipulationSourceStream::SetCustomContext
PartyAudioManipulationSourceStream::SetCustomContext
5/24/2022 • 2 minutes to read • Edit Online

Configures an optional, custom pointer-sized context value with this stream object.

Syntax
PartyError SetCustomContext(
void* customContext
)

Parameters
customContext void*
optional
An arbitrary, pointer-sized value to store with the network object.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
The custom context is typically used as a "shortcut" that simplifies accessing local, title-specific memory
associated with the network without requiring a mapping lookup. The value is retrieved using the
GetCustomContext() method.

Any configured value is treated as opaque by the library, and is only valid on the local device; it is not
transmitted over the network.

Requirements
Header : Party.h

See also
PartyAudioManipulationSourceStream
PartyAudioManipulationSourceStream::GetCustomContext
PartyChatControl
5/24/2022 • 2 minutes to read • Edit Online

The management class for chat operations.

Syntax
class PartyChatControl

Public Methods
NAME DESC RIP T IO N

GetLocal Gets the PartyLocalChatControl version of this chat control.

GetDevice Returns the device this chat control is associated with.

GetEntityId Gets the PlayFab Entity ID of the user associated with this
chat control.

GetNetworks Gets the networks to which this chat control is connected.

GetCustomContext Retrieves the app's private, custom pointer-sized context


value previously associated with this chat control object.

SetCustomContext Configures an optional, custom pointer-sized context value


with this chat control object.

ConfigureAudioManipulationVoiceStream Queues an asynchronous operation to configure the audio


manipulation voice stream associated with this chat control.

GetAudioManipulationVoiceStream Retrieves the audio manipulation voice stream associated


with this chat control.

Requirements
Header : Party.h

See also
Party members
PartyLocalChatControl
PartyChatControl::GetLocal
5/24/2022 • 2 minutes to read • Edit Online

Gets the PartyLocalChatControl version of this chat control.

Syntax
PartyError GetLocal(
PartyLocalChatControl** localChatControl
)

Parameters
localChatControl PartyLocalChatControl**
library-allocated output, may return nullptr
The local version of this chat control object, or nullptr if this is not a local chat control.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Requirements
Header : Party.h

See also
PartyChatControl
PartyChatControl::GetDevice
5/24/2022 • 2 minutes to read • Edit Online

Returns the device this chat control is associated with.

Syntax
PartyError GetDevice(
PartyDevice** device
)

Parameters
device PartyDevice**
library-allocated output
The output device this chat control is associated with.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Requirements
Header : Party.h

See also
PartyChatControl
PartyChatControl::GetEntityId
5/24/2022 • 2 minutes to read • Edit Online

Gets the PlayFab Entity ID of the user associated with this chat control.

Syntax
PartyError GetEntityId(
PartyString* entityId
)

Parameters
entityId PartyString*
library-allocated output
The output Entity ID.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
The memory for the Entity ID string remains valid for the life of the chat control, which is until its
PartyChatControlDestroyedStateChange and/or PartyDestroyChatControlCompletedStateChange, depending on
the type of destruction that occurred, has been provided via PartyManager::StartProcessingStateChanges() and
all state changes referencing the chat control have been returned to
PartyManager::FinishProcessingStateChanges().

Requirements
Header : Party.h

See also
PartyChatControl
PartyChatControl::GetNetworks
5/24/2022 • 2 minutes to read • Edit Online

Gets the networks to which this chat control is connected.

Syntax
PartyError GetNetworks(
uint32_t* networkCount,
PartyNetworkArray* networks
)

Parameters
networkCount uint32_t*
output
The output number of networks to which this chat control is connected.
networks PartyNetworkArray*
library-allocated output array of size *networkCount

A library-allocated output array containing the networks to which this chat control is connected.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
Once a PartyChatControlLeftNetworkStateChange has been provided by
PartyManager::StartProcessingStateChanges(), the network will no longer be present in the array returned by
this method.

The memory for the returned array is invalidated whenever the title calls
PartyManager::StartProcessingStateChanges() or PartyNetwork::ConnectChatControl() returns success.

Requirements
Header : Party.h

See also
PartyChatControl
PartyNetwork::ConnectChatControl
PartyNetwork::DisconnectChatControl
PartyChatControlLeftNetworkStateChange
PartyChatControl::GetCustomContext
5/24/2022 • 2 minutes to read • Edit Online

Retrieves the app's private, custom pointer-sized context value previously associated with this chat control
object.

Syntax
PartyError GetCustomContext(
void** customContext
)

Parameters
customContext void**
output, may return nullptr
The output custom context.
Return value
PartyError
c_partyErrorSuccess if retrieving the custom context succeeded or an error code otherwise. The human-
readable form of the error code can be retrieved via PartyManager::GetErrorMessage().

Remarks
If no custom context has been set yet, the value pointed to by customContext is set to nullptr.

Requirements
Header : Party.h

See also
PartyChatControl
PartyChatControl::SetCustomContext
PartyChatControl::SetCustomContext
5/24/2022 • 2 minutes to read • Edit Online

Configures an optional, custom pointer-sized context value with this chat control object.

Syntax
PartyError SetCustomContext(
void* customContext
)

Parameters
customContext void*
optional
An arbitrary, pointer-sized value to store with the chat control object.
Return value
PartyError
c_partyErrorSuccess if configuring the custom context succeeded or an error code otherwise. The human-
readable form of the error code can be retrieved via PartyManager::GetErrorMessage().

Remarks
The custom context is typically used as a "shortcut" that simplifies accessing local, title-specific memory
associated with the chat control without requiring a mapping lookup. The value is retrieved using the
GetCustomContext() method.

Any configured value is treated as opaque by the library, and is only valid on the local device; it is not
transmitted over the network.

Requirements
Header : Party.h

See also
PartyChatControl
PartyChatControl::GetCustomContext
PartyChatControl::ConfigureAudioManipulationVoiceStream
5/24/2022 • 2 minutes to read • Edit Online

Queues an asynchronous operation to configure the audio manipulation voice stream associated with this chat
control.

Syntax
PartyError ConfigureAudioManipulationVoiceStream(
PartyAudioManipulationSourceStreamConfiguration* configuration,
void* asyncIdentifier
)

Parameters
configuration PartyAudioManipulationSourceStreamConfiguration*
optional
The stream configuration.
asyncIdentifier void*
optional
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
If the configuration is non-null, an audio manipulation voice stream will be created for this chat control. Such a
stream redirects output for the voice audio associated with this chat control; instead of the library automatically
handling the voice audio and routing it, the app can use the source stream to retrieve the voice audio and route
it via game logic. If the configuration is null, and a voice stream has previously been configured, the voice
stream will be destroyed.

Upon completion of the asynchronous operation, when a non-null configuration was specified, a voice stream
for this chat control can be queried via PartyChatControl::GetAudioManipulationVoiceStream(). Completion is
indicated by a PartyConfigureAudioManipulationVoiceStreamCompletedStateChange.
Platform support and supported formats
This function is only supported on Windows and Xbox. Calls on other platforms will fail.

The following format options are supported.

SUP P O RT ED VA L UE F O R LO C A L C H AT SUP P O RT ED VA L UE F O R REM OT E


F O RM AT O P T IO N C O N T RO L S C H AT C O N T RO L S

Samples per second 24 kHz 24 kHz


SUP P O RT ED VA L UE F O R LO C A L C H AT SUP P O RT ED VA L UE F O R REM OT E
F O RM AT O P T IO N C O N T RO L S C H AT C O N T RO L S

Channel mask 0 0

Channel count 1 1

Bits per sample 32 16

Sample type PartyAudioSampleType::Float PartyAudioSampleType::Integer

Interleaved false false

Requirements
Header : Party.h

See also
PartyChatControl
PartyChatControl::GetAudioManipulationVoiceStream
5/24/2022 • 2 minutes to read • Edit Online

Retrieves the audio manipulation voice stream associated with this chat control.

Syntax
PartyError GetAudioManipulationVoiceStream(
PartyAudioManipulationSourceStream** sourceStream
)

Parameters
sourceStream PartyAudioManipulationSourceStream**
library-allocated output
The source stream.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
If this is a local chat control, the stream represents the voice audio detected by the local audio input. Audio
provided by this stream will have already been preprocessed with Voice Activity Detection (VAD) and Automatic
Gain Control (AGC). Audio will only be provided when voice activity is detected. Typically, the app will retrieve
audio from this stream via PartyAudioManipulationSourceStream::GetNextBuffer(), process the audio using app
logic, and then submit the audio back to the library. The audio is submitted back to the library by retrieving the
voice sink stream via PartyLocalChatControl::GetAudioManipulationCaptureStream() and then submitting the
buffer via PartyAudioManipulationSinkStream::SubmitBuffer().

Audio generated via PartyLocalChatControl::SynthesizeTextToSpeech() of type


PartySynthesizeTextToSpeechType::VoiceChat will be provided via this source stream, because such audio acts as
the associated user's voice.

Audio retrieved via this stream will not have been transcribed via speech-to-text for voice chat transcription.
Audio that is submitted to a sink stream via PartyAudioManipulationSinkStream::SubmitBuffer() will be
transcribed, if transcription options configured via PartyLocalChatControl::SetTranscriptionOptions indicates that
audio associated the sink's chat control should be.

If this a remote chat control, the stream represents the chat control's incoming voice audio. Typically, the app will
retrieve audio from the voice streams associated with all remote chat controls via
PartyAudioManipulationSourceStream::GetNextBuffer(), process and mix each buffer into a single audio stream,
and then submit the mixed stream to be rendered by each appropriate sink stream. Each render stream can be
retrieved via PartyLocalChatControl::GetAudioManipulationRenderStream().

Requirements
Header : Party.h

See also
PartyChatControl
PartyDevice
5/24/2022 • 2 minutes to read • Edit Online

Represents a device across networks.

Syntax
class PartyDevice

Public Methods
NAME DESC RIP T IO N

GetLocal Gets the PartyLocalDevice version of this device.

GetChatControls Gets the chat controls on this device.

GetCustomContext Retrieves the app's private, custom pointer-sized context


value previously associated with this device object.

SetCustomContext Configures an optional, custom pointer-sized context value


with this device object.

Requirements
Header : Party.h

See also
Party members
PartyLocalDevice
PartyDevice::GetLocal
5/24/2022 • 2 minutes to read • Edit Online

Gets the PartyLocalDevice version of this device.

Syntax
PartyError GetLocal(
PartyLocalDevice** localDevice
)

Parameters
localDevice PartyLocalDevice**
library-allocated output, may return nullptr
The output local version of this device object, or nullptr if this is not a local device.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Requirements
Header : Party.h

See also
PartyDevice
PartyDevice::GetChatControls
5/24/2022 • 2 minutes to read • Edit Online

Gets the chat controls on this device.

Syntax
PartyError GetChatControls(
uint32_t* chatControlCount,
PartyChatControlArray* chatControls
)

Parameters
chatControlCount uint32_t*
output
The output number of chat controls on this device.
chatControls PartyChatControlArray*
library-allocated output array of size *chatControlCount
A library-allocated output array containing the chat controls on this device.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
Once a PartyChatControlDestroyedStateChange has been provided by
PartyManager::StartProcessingStateChanges(), the chat control will no longer be present in the array returned
by this method.

The memory for the returned array is invalidated whenever the title calls
PartyManager::StartProcessingStateChanges(). If this is the local device, the memory for the array is also
invalidated when PartyLocalDevice::CreateChatControl() returns success.

Requirements
Header : Party.h

See also
PartyDevice
PartyLocalDevice::CreateChatControl
PartyLocalDevice::DestroyChatControl
PartyChatControlDestroyedStateChange
PartyDevice::GetCustomContext
5/24/2022 • 2 minutes to read • Edit Online

Retrieves the app's private, custom pointer-sized context value previously associated with this device object.

Syntax
PartyError GetCustomContext(
void** customContext
)

Parameters
customContext void**
output, may return nullptr
The output custom context.
Return value
PartyError
c_partyErrorSuccess if retrieving the custom context succeeded or an error code otherwise. The human-
readable form of the error code can be retrieved via PartyManager::GetErrorMessage().

Remarks
If no custom context has been set yet, the value pointed to by customContext is set to nullptr.

Requirements
Header : Party.h

See also
PartyDevice
PartyDevice::SetCustomContext
PartyDevice::SetCustomContext
5/24/2022 • 2 minutes to read • Edit Online

Configures an optional, custom pointer-sized context value with this device object.

Syntax
PartyError SetCustomContext(
void* customContext
)

Parameters
customContext void*
optional
An arbitrary, pointer-sized value to store with the device object.
Return value
PartyError
c_partyErrorSuccess if configuring the custom context succeeded or an error code otherwise. The human-
readable form of the error code can be retrieved via PartyManager::GetErrorMessage().

Remarks
The custom context is typically used as a "shortcut" that simplifies accessing local, title-specific memory
associated with the device without requiring a mapping lookup. The value is retrieved using the
GetCustomContext() method.

Any configured value is treated as opaque by the library, and is only valid on the local device; it is not
transmitted over the network.

Requirements
Header : Party.h

See also
PartyDevice
PartyDevice::GetCustomContext
PartyEndpoint
5/24/2022 • 2 minutes to read • Edit Online

Represents an endpoint in a network.

Syntax
class PartyEndpoint

Public Methods
NAME DESC RIP T IO N

GetLocal Gets the PartyLocalEndpoint version of this endpoint.

GetEntityId Gets the PlayFab Entity ID of the user associated with this
endpoint.

GetNetwork Gets the network associated with this endpoint.

GetDevice Gets the device associated with this endpoint.

GetUniqueIdentifier Gets the network-unique identifier for this endpoint.

GetCustomContext Retrieves the app's private, custom pointer-sized context


value previously associated with this endpoint object.

SetCustomContext Configures an optional, custom pointer-sized context value


with this endpoint object.

Requirements
Header : Party.h

See also
Party members
PartyLocalEndpoint
PartyEndpoint::GetLocal
5/24/2022 • 2 minutes to read • Edit Online

Gets the PartyLocalEndpoint version of this endpoint.

Syntax
PartyError GetLocal(
PartyLocalEndpoint** localEndpoint
)

Parameters
localEndpoint PartyLocalEndpoint**
library-allocated output, may return nullptr
The output local version of this endpoint object, or nullptr if this is not a local endpoint.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Requirements
Header : Party.h

See also
PartyEndpoint
PartyEndpoint::GetEntityId
5/24/2022 • 2 minutes to read • Edit Online

Gets the PlayFab Entity ID of the user associated with this endpoint.

Syntax
PartyError GetEntityId(
PartyString* entityId
)

Parameters
entityId PartyString*
library-allocated output, may return nullptr
The output Entity ID of ther user associated with this endpoint, or nullptr.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
If this endpoint is not associated with a user, entityId is set to nullptr.

The memory for the Entity ID string remains valid for the life of the endpoint, which is until its
PartyEndpointDestroyedStateChange and/or PartyDestroyEndpointCompletedStateChange, depending on the
type of destruction that occurred, has been provided via PartyManager::StartProcessingStateChanges() and all
state changes referencing the endpoint have been returned to PartyManager::FinishProcessingStateChanges().

Requirements
Header : Party.h

See also
PartyEndpoint
PartyEndpoint::GetNetwork
5/24/2022 • 2 minutes to read • Edit Online

Gets the network associated with this endpoint.

Syntax
PartyError GetNetwork(
PartyNetwork** network
)

Parameters
network PartyNetwork**
library-allocated output
The output network associated with this endpoint.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Requirements
Header : Party.h

See also
PartyEndpoint
PartyEndpoint::GetDevice
5/24/2022 • 2 minutes to read • Edit Online

Gets the device associated with this endpoint.

Syntax
PartyError GetDevice(
PartyDevice** device
)

Parameters
device PartyDevice**
library-allocated output
The output device associated with this endpoint.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Requirements
Header : Party.h

See also
PartyEndpoint
PartyEndpoint::GetUniqueIdentifier
5/24/2022 • 2 minutes to read • Edit Online

Gets the network-unique identifier for this endpoint.

Syntax
PartyError GetUniqueIdentifier(
uint16_t* uniqueIdentifier
)

Parameters
uniqueIdentifier uint16_t*
output
The output unique identifier.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
This identifier is unique within the endpoint's network and is consistent across all endpoints in a network. It is
intended to be used as a compact option for titles to refer to specific endpoints in
PartyLocalEndpoint::SendMessage() data buffers without much bandwidth overhead or the need to manually
negotiate identifiers. This identifier is not unique across networks.

For local endpoints, this method will fail until the PartyEndpointCreatedStateChange has been provided by
PartyManager::StartProcessingStateChanges(). For remote endpoints, this method will always succeed.

All devices in a network will agree on a given endpoint's unique identifier, but different devices may not see the
same endpoints at a given moment. For example, it's possible for endpoint A to send a message to endpoint B
that references a newly-created endpoint C's unique identifier, but that message between A and B may arrive
before the PartyEndpointCreatedStateChange for endpoint C is generated on endpoint B's device.

Requirements
Header : Party.h

See also
PartyEndpoint
PartyEndpointCreatedStateChange
PartyNetwork::FindEndpointByUniqueIdentifier
PartyEndpoint::GetCustomContext
5/24/2022 • 2 minutes to read • Edit Online

Retrieves the app's private, custom pointer-sized context value previously associated with this endpoint object.

Syntax
PartyError GetCustomContext(
void** customContext
)

Parameters
customContext void**
output, may return nullptr
The output custom context.
Return value
PartyError
c_partyErrorSuccess if retrieving the custom context succeeded or an error code otherwise. The human-
readable form of the error code can be retrieved via PartyManager::GetErrorMessage().

Remarks
If no custom context has been set yet, the value pointed to by customContext is set to nullptr.

Requirements
Header : Party.h

See also
PartyEndpoint
PartyEndpoint::SetCustomContext
PartyEndpoint::SetCustomContext
5/24/2022 • 2 minutes to read • Edit Online

Configures an optional, custom pointer-sized context value with this endpoint object.

Syntax
PartyError SetCustomContext(
void* customContext
)

Parameters
customContext void*
optional
An arbitrary, pointer-sized value to store with the endpoint object.
Return value
PartyError
c_partyErrorSuccess if configuring the custom context succeeded or an error code otherwise. The human-
readable form of the error code can be retrieved via PartyManager::GetErrorMessage().

Remarks
The custom context is typically used as a "shortcut" that simplifies accessing local, title-specific memory
associated with the endpoint without requiring a mapping lookup. The value is retrieved using the
GetCustomContext() method.

Any configured value is treated as opaque by the library, and is only valid on the local device; it is not
transmitted over the network.

Requirements
Header : Party.h

See also
PartyEndpoint
PartyEndpoint::GetCustomContext
PartyInvitation
5/24/2022 • 2 minutes to read • Edit Online

Represents an invitation used to authenticate a user into a network.

Syntax
class PartyInvitation

Public Methods
NAME DESC RIP T IO N

GetCreatorEntityId Gets the PlayFab Entity ID of the user that created this
invitation or nullptr if this invitation was generated as part of
a PartyManager::CreateNewNetwork() operation.

GetInvitationConfiguration Gets this invitation's configuration.

GetCustomContext Retrieves the app's private, custom pointer-sized context


value previously associated with this invitation object.

SetCustomContext Configures an optional, custom pointer-sized context value


with this invitation object.

Requirements
Header : Party.h

See also
Party members
PartyManager::CreateNewNetwork
PartyNetwork::CreateInvitation
PartyNetwork::AuthenticateLocalUser
PartyInvitationConfiguration
PartyInvitation::GetCreatorEntityId
5/24/2022 • 2 minutes to read • Edit Online

Gets the PlayFab Entity ID of the user that created this invitation or nullptr if this invitation was generated as part
of a PartyManager::CreateNewNetwork() operation.

Syntax
PartyError GetCreatorEntityId(
PartyString* entityId
)

Parameters
entityId PartyString*
library-allocated output, may return nullptr
The output Entity ID of the user that created this invitation, or nullptr.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Requirements
Header : Party.h

See also
PartyInvitation
PartyInvitation::GetInvitationConfiguration
5/24/2022 • 2 minutes to read • Edit Online

Gets this invitation's configuration.

Syntax
PartyError GetInvitationConfiguration(
const PartyInvitationConfiguration** configuration
)

Parameters
configuration PartyInvitationConfiguration**
library-allocated output
The output configuration of this invitation.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
The memory for the PartyInvitationConfiguration and all memory it references are valid for the lifetime of the
invitation object.

Requirements
Header : Party.h

See also
PartyInvitation
PartyInvitationConfiguration
PartyInvitation::GetCustomContext
5/24/2022 • 2 minutes to read • Edit Online

Retrieves the app's private, custom pointer-sized context value previously associated with this invitation object.

Syntax
PartyError GetCustomContext(
void** customContext
)

Parameters
customContext void**
output, may return nullptr
The output custom context.
Return value
PartyError
c_partyErrorSuccess if retrieving the custom context succeeded or an error code otherwise. The human-
readable form of the error code can be retrieved via PartyManager::GetErrorMessage().

Remarks
If no custom context has been set yet, the value pointed to by customContext is set to nullptr.

Requirements
Header : Party.h

See also
PartyInvitation
PartyInvitation::SetCustomContext
PartyInvitation::SetCustomContext
5/24/2022 • 2 minutes to read • Edit Online

Configures an optional, custom pointer-sized context value with this invitation object.

Syntax
PartyError SetCustomContext(
void* customContext
)

Parameters
customContext void*
optional
An arbitrary, pointer-sized value to store with the invitation object.
Return value
PartyError
c_partyErrorSuccess if configuring the custom context succeeded or an error code otherwise. The human-
readable form of the error code can be retrieved via PartyManager::GetErrorMessage().

Remarks
The custom context is typically used as a "shortcut" that simplifies accessing local, title-specific memory
associated with the invitation without requiring a mapping lookup. The value is retrieved using the
GetCustomContext() method.

Any configured value is treated as opaque by the library, and is only valid on the local device; it is not
transmitted over the network.

Requirements
Header : Party.h

See also
PartyInvitation
PartyInvitation::GetCustomContext
PartyLocalChatControl
5/24/2022 • 2 minutes to read • Edit Online

The management class for chat operations related to the local device.

Syntax
class PartyLocalChatControl : public PartyChatControl

Public Methods
NAME DESC RIP T IO N

GetLocalUser Gets the local user associated with this local chat control.

SetPermissions Sets the chat permissions between the local chat control and
a target chat control.

GetPermissions Gets the voice communication relationship between the local


chat control and a target chat control.

SendText Transmits a chat text string to each specified target chat


control.

SetAudioInput Configures the preferred microphone or recording device


that the chat control will use for audio input.

GetAudioInput Provides the preferred microphone or recording device that


the chat control has been configured to use for audio input.

SetAudioOutput Configures the preferred speakers or headset device that the


chat control will use for audio output.

GetAudioOutput Provides the preferred speakers or headset device that the


chat control has been configured to use for audio output.

PopulateAvailableTextToSpeechProfiles Populates the local chat control's list of supported text to


speech profiles.

GetAvailableTextToSpeechProfiles Gets the text to speech profiles for this chat control.

SetTextToSpeechProfile Configures the profile to use for a specified type of text-to-


speech operation.

GetTextToSpeechProfile Gets the profile that was last configured from a successfully
completed SetTextToSpeechProfile() operation for a specified
type of text-to-speech operation.
NAME DESC RIP T IO N

SynthesizeTextToSpeech Generates text-to-speech audio that is used to either


displace the microphone audio associated with this chat
control or render directly to the chat control's audio output.

GetLanguage Gets the language associated with this chat control.

SetTranscriptionOptions Configures the transcription options associated with voice


chat audio for this chat control.

GetTranscriptionOptions Provides the transcription options associated with voice chat


audio for this chat control.

SetTextChatOptions Configures the text chat options associated with text chat for
this chat control.

GetTextChatOptions Provides the text chat options associated with text chat for
this chat control.

SetAudioRenderVolume Configures the volume setting for audio received from a


target chat control that will be used for the local chat
control.

GetAudioRenderVolume Provides the volume setting for audio received from a target
chat control that will be used for the local chat control.

SetAudioInputMuted Configures whether the user's audio input is in the mute


state.

GetAudioInputMuted Provides whether the user's audio input is in the mute state.

SetIncomingAudioMuted Configures whether the incoming audio from the target chat
control, in relation to the local chat control, is muted.

GetIncomingAudioMuted Provides whether the incoming audio from the target chat
control, in relation to the local chat control, has previously
been muted.

SetIncomingTextMuted Configures whether the incoming text messages from the


target chat control, in relation to the local chat control, is
muted.

GetIncomingTextMuted Provides whether the incoming text messages from the


target chat control, in relation to the local chat control, has
previously been muted.

GetLocalChatIndicator Provides a chat indicator specifying the audio state of the


local chat control.

GetChatIndicator Provides a chat indicator specifying the audio state of a


target chat control in relation to the local chat control.

ConfigureAudioManipulationCaptureStream Queues an asynchronous operation to configure the audio


manipulation capture stream.
NAME DESC RIP T IO N

GetAudioManipulationCaptureStream Retrieves the audio manipulation capture stream associated


with this chat control.

ConfigureAudioManipulationRenderStream Queues an asynchronous operation to configure the audio


manipulation render stream.

GetAudioManipulationRenderStream Retrieves the manipulation render stream associated with


this chat control.

Requirements
Header : Party.h

See also
Party members
PartyChatControl
PartyChatControl::GetLocal
PartyLocalChatControl::GetLocalUser
5/24/2022 • 2 minutes to read • Edit Online

Gets the local user associated with this local chat control.

Syntax
PartyError GetLocalUser(
PartyLocalUser** localUser
)

Parameters
localUser PartyLocalUser**
library-allocated output
The output local user.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Requirements
Header : Party.h

See also
PartyLocalChatControl
PartyLocalChatControl::SetPermissions
5/24/2022 • 2 minutes to read • Edit Online

Sets the chat permissions between the local chat control and a target chat control.

Syntax
PartyError SetPermissions(
const PartyChatControl* targetChatControl,
PartyChatPermissionOptions chatPermissionOptions
)

Parameters
targetChatControl PartyChatControl*
The target chat control.
chatPermissionOptions PartyChatPermissionOptions
The chat permission options.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
Chat permissions allow you to control incoming and outgoing voice communication, as well as incoming text
communication, between any pair of chat controls. The chat permissions should be configured to reflect your
target scenario. For example, if the target chat control is a member of the same team, you'd likely allow audio in
both directions. If the target chat control is a member of an opposing team, you likely wouldn't allow audio in
either direction. Regardless of team, you might allow receiving text.

The target chat control must be remote. The default permission is PartyChatPermissionOptions::None.

This setting is local only. If a local chat control is configured to send audio to a remote chat control, no audio will
be sent to the remote chat control unless the remote chat control has also been configured to receive audio
from the local chat control in their instance of the library. Similarly, if a local chat control is configured to receive
audio from a remote chat control, no audio will be received from the remote chat control unless the remote chat
control has also been configured to send audio to the local chat control in their instance of the library. Therefore,
both chat controls must agree that the communication is allowed; one chat control can't force another to accept
or transmit undesired chat.

There is no permission associated with sending chat text because each call to SendText() requires an explicit list
of target chat controls. Including or omitting a target is equivalent to granting or denying send permission for
that text message. The target still must have set PartyChatPermissionOptions::ReceiveText in their instance of the
library for it to actually be delivered.
The Party library does not enforce platform restrictions tied to the user's identity, such as a platform setting that
restricts chat to "friends only". Platform restrictions should be considered when configuring the chat
permissions between two chat controls.

Requirements
Header : Party.h

See also
PartyLocalChatControl
PartyLocalChatControl::GetPermissions
5/24/2022 • 2 minutes to read • Edit Online

Gets the voice communication relationship between the local chat control and a target chat control.

Syntax
PartyError GetPermissions(
const PartyChatControl* targetChatControl,
PartyChatPermissionOptions* chatPermissionOptions
)

Parameters
targetChatControl PartyChatControl*
The target chat control.
chatPermissionOptions PartyChatPermissionOptions*
output
The output chat permission options.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Requirements
Header : Party.h

See also
PartyLocalChatControl
PartyLocalChatControl::SendText
5/24/2022 • 2 minutes to read • Edit Online

Transmits a chat text string to each specified target chat control.

Syntax
PartyError SendText(
uint32_t targetChatControlCount,
PartyChatControlArray targetChatControls,
PartyString chatText,
uint32_t dataBufferCount,
const PartyDataBuffer* dataBuffers
)

Parameters
targetChatControlCount uint32_t
The number of target chat controls in the targetChatControls array.
targetChatControls PartyChatControlArray
input array of size targetChatControlCount

The targetChatControlCount entry array of target PartyChatControls.


chatText PartyString
The text to send.
dataBufferCount uint32_t
The number of buffer structures provided in the dataBuffers array.
dataBuffers PartyDataBuffer*
input array of size dataBufferCount
The dataBufferCount entry array of PartyDataBuffer structures describing an auxiliary message payload to send.
This is ignored when dataBufferCount is zero.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
Sending chat text to local chat controls is not currently supported. If the array of target chat controls includes
any local targets, this call will synchronously fail.

There is no guaranteed translation, localization, or offensive language filtering of the text content; the chat text
string will be presented with the text as is.
The text string will only be delivered to target chat controls that have configured their own instances to receive
text messages from the local chat control via PartyLocalChatControl::SetPermissions().

If a target chat control is not connected to at least one network in common with the source chat control, the text
string will not be delivered. This is possible if there are two local chat controls. A target chat control connected to
one of the local chat controls may not be connected to all other local chat controls.

The PartyDataBuffer structures in the dataBuffers array are for auxiliary data associated with the chat text, such
as metadata indicating the color that should be used to render the text or a binary blob containing image data
for an icon to render along with the chat text. For sending game data that is unrelated to text chat, see
PartyLocalEndpoint::SendMessage(), a messaging option that exposes finer control over message transmission
behavior.

Callers provide 0 or more PartyDataBuffer structures in the dataBuffers array. The memory that the structures
reference does not have to be contiguous, making it easy to have a fixed header buffer followed by a variable
payload, for example. The buffers will be assembled in order, transmitted, and delivered to the targeted chat
controls as a single contiguous data block, separate from the chat text, in a PartyChatTextReceivedStateChange.
The Party library does not expend bandwidth transmitting metadata to describe the original PartyDataBuffer
segmentation.

Requirements
Header : Party.h

See also
PartyLocalChatControl
PartyChatTextReceivedStateChange
PartyLocalChatControl::SetAudioInput
5/24/2022 • 2 minutes to read • Edit Online

Configures the preferred microphone or recording device that the chat control will use for audio input.

Syntax
PartyError SetAudioInput(
PartyAudioDeviceSelectionType audioDeviceSelectionType,
PartyString audioDeviceSelectionContext,
void* asyncIdentifier
)

Parameters
audioDeviceSelectionType PartyAudioDeviceSelectionType
If PartyAudioDeviceSelectionType::None is specified, the audio input will be cleared. If
PartyAudioDeviceSelectionType::SystemDefault is specified, the Party library will attempt to use the system's
default communication device. If PartyAudioDeviceSelectionType::PlatformUserDefault is specified, the Party
library will attempt to use the default communication device associated with audioDeviceSelectionContext . If
PartyAudioDeviceSelectionType::Manual is specified, the Party library will attempt to use the communication
device whose device identifier matches. Note that this is not supported on iOS or Android.
audioDeviceSelectionContext .

audioDeviceSelectionContext PartyString
optional
When using PartyAudioDeviceSelectionType::None or PartyAudioDeviceSelectionType::SystemDefault,
audioDeviceSelectionContext will be ignored. When using PartyAudioDeviceSelectionType::PlatformUserDefault,
audioDeviceSelectionContext must be the non-null, non-empty platform-specific user context that the chat
control should use when selecting the audio device. When using PartyAudioDeviceSelectionType::Manual,
audioDeviceSelectionContext must be the non-null, non-empty identifier of the audio device that the chat
control should use.
asyncIdentifier void*
optional
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
Return value
PartyError
c_partyErrorSuccess if the asynchronous operation to set the audio input began, or an error code otherwise. If
this method fails, no related state changes will be generated. The human-readable form of the error code can be
retrieved via PartyManager::GetErrorMessage().

Remarks
This method queues an asynchronous operation to configure the preferred recording device associated with this
local chat control. If the method succeeds, a PartyLocalChatAudioInputChangedStateChange will be provided by
PartyManager::StartProcessingStateChanges() with details about the input device status and a
PartySetChatAudioInputCompletedStateChange will be provided upon completion of the operation, indicating
success or failure. After completion, an additional PartyLocalChatAudioInputChangedStateChange will be
provided each time the audio device status changes, such as due to device removal.

If the specified device isn't present, the chat control will subscribe to audio device changes and use the device
when it does appear.

When using the PlatformUserDefault option on the Xbox platform, the Xbox User Identifier (XUID) must be
passed as the audioDeviceSelectionContext value.

Requirements
Header : Party.h

See also
PartyLocalChatControl
PartyLocalChatControl::GetAudioInput
PartyLocalChatControl::SetAudioOutput
PartyLocalChatControl::GetAudioInput
5/24/2022 • 2 minutes to read • Edit Online

Provides the preferred microphone or recording device that the chat control has been configured to use for
audio input.

Syntax
PartyError GetAudioInput(
PartyAudioDeviceSelectionType* audioDeviceSelectionType,
PartyString* audioDeviceSelectionContext,
PartyString* deviceId
)

Parameters
audioDeviceSelectionType PartyAudioDeviceSelectionType*
output
An output value indicating the selection type that was used to select the provided deviceId .
audioDeviceSelectionContext PartyString*
library-allocated output
When using PartyAudioDeviceSelectionType::None or PartyAudioDeviceSelectionType::SystemDefault,
audioDeviceSelectionContext will be empty. When using PartyAudioDeviceSelectionType::PlatformUserDefault
or PartyAudioDeviceSelectionType::Manual, audioDeviceSelectionContext will be the value provided in a
previous call to SetAudioInput(). The memory for the string remains valid until the next
PartyLocalChatAudioInputChangedStateChange is provided via PartyManager::StartProcessingStateChanges() or
the chat control is destroyed.
deviceId PartyString*
library-allocated output
An output value indicating the selected audio input device's identifier. The memory for the string remains valid
until the next PartyLocalChatAudioInputChangedStateChange is provided via
PartyManager::StartProcessingStateChanges() or the chat control is destroyed.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
An empty device identifier string indicates that no input has been selected.

Requirements
Header : Party.h
See also
PartyLocalChatControl
PartyLocalChatControl::SetAudioInput
PartyLocalChatControl::GetAudioOutput
PartyLocalChatControl::SetAudioOutput
5/24/2022 • 2 minutes to read • Edit Online

Configures the preferred speakers or headset device that the chat control will use for audio output.

Syntax
PartyError SetAudioOutput(
PartyAudioDeviceSelectionType audioDeviceSelectionType,
PartyString audioDeviceSelectionContext,
void* asyncIdentifier
)

Parameters
audioDeviceSelectionType PartyAudioDeviceSelectionType
If PartyAudioDeviceSelectionType::None is specified, the audio output will be cleared. If
PartyAudioDeviceSelectionType::SystemDefault is specified, the Party library will attempt to use the system's
default communication device. If PartyAudioDeviceSelectionType::PlatformUserDefault is specified, the Party
library will attempt to use the default communication device associated with audioDeviceSelectionContext . If
PartyAudioDeviceSelectionType::Manual is specified, the Party library will attempt to use the communication
device whose device identifier matches audioDeviceSelectionContext .
audioDeviceSelectionContext PartyString
optional
When using PartyAudioDeviceSelectionType::None or PartyAudioDeviceSelectionType::SystemDefault,
audioDeviceSelectionContext will be ignored. When using PartyAudioDeviceSelectionType::PlatformUserDefault,
audioDeviceSelectionContext must be the non-null, non-empty platform-specific user context that the chat
control should use when selecting the audio device. When using PartyAudioDeviceSelectionType::Manual,
audioDeviceSelectionContext must be the non-null, non-empty identifier of the audio device that the chat
control should use.
asyncIdentifier void*
optional
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
Return value
PartyError
c_partyErrorSuccess if the asynchronous operation to set the audio output began, or an error code otherwise. If
this method fails, no related state changes will be generated. The human-readable form of the error code can be
retrieved via PartyManager::GetErrorMessage().

Remarks
This method queues an asynchronous operation to configure the preferred speakers or headset device
associated with this local chat control. If the method succeeds, a
PartyLocalChatAudioOutputChangedStateChange will be provided by
PartyManager::StartProcessingStateChanges() with details about the output device status and a
PartySetChatAudioOutputCompletedStateChange will be provided upon completion of the operation, indicating
success or failure. After completion, an additional PartyLocalChatAudioOutputChangedStateChange will be
provided each time the audio device status changes, such as due to device removal.

If the specified device isn't present, the chat control will subscribe to audio device changes and use the device
when it does appear.

When using the PlatformUserDefault option on the Xbox platform, the Xbox User Identifier (XUID) must be
passed as the audioDeviceSelectionContext value.

Requirements
Header : Party.h

See also
PartyLocalChatControl
PartyLocalChatControl::GetAudioOutput
PartyLocalChatControl::SetAudioInput
PartyLocalChatControl::GetAudioOutput
5/24/2022 • 2 minutes to read • Edit Online

Provides the preferred speakers or headset device that the chat control has been configured to use for audio
output.

Syntax
PartyError GetAudioOutput(
PartyAudioDeviceSelectionType* audioDeviceSelectionType,
PartyString* audioDeviceSelectionContext,
PartyString* deviceId
)

Parameters
audioDeviceSelectionType PartyAudioDeviceSelectionType*
output
An output value indicating the selection type that was used to select the provided deviceId .
audioDeviceSelectionContext PartyString*
library-allocated output
When using PartyAudioDeviceSelectionType::None or PartyAudioDeviceSelectionType::SystemDefault,
audioDeviceSelectionContext will be empty. When using PartyAudioDeviceSelectionType::PlatformUserDefault
or PartyAudioDeviceSelectionType::Manual, audioDeviceSelectionContext will be the value provided in a
previous call to SetAudioOutput(). The memory for the string remains valid until the next
PartyLocalChatAudioOutputChangedStateChange is provided via PartyManager::StartProcessingStateChanges()
or the chat control is destroyed.
deviceId PartyString*
library-allocated output
An output value indicating the selected audio output device's identifier. The memory for the string remains valid
until the next PartyLocalChatAudioOutputChangedStateChange is provided via
PartyManager::StartProcessingStateChanges() or the chat control is destroyed.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
An empty device identifier string indicates that no output has been selected.

Requirements
Header : Party.h
See also
PartyLocalChatControl
PartyLocalChatControl::SetAudioOutput
PartyLocalChatControl::GetAudioInput
PartyLocalChatControl::PopulateAvailableTextToSpeechProfiles
5/24/2022 • 2 minutes to read • Edit Online

Populates the local chat control's list of supported text to speech profiles.

Syntax
PartyError PopulateAvailableTextToSpeechProfiles(
void* asyncIdentifier
)

Parameters
asyncIdentifier void*
optional
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
Return value
PartyError
c_partyErrorSuccess if the asynchronous operation began, or an error code otherwise. If this method fails, no
related state changes will be generated. The human-readable form of the error code can be retrieved via
PartyManager::GetErrorMessage().

Remarks
This is an asynchronous operation; a PartyPopulateAvailableTextToSpeechProfilesCompletedStateChange will be
provided via PartyManager::StartProcessingStateChanges() on completion.

The asynchronous operation must complete successfully before GetAvailableTextToSpeechProfiles() can be


called.

Requirements
Header : Party.h

See also
PartyLocalChatControl
PartyLocalChatControl::GetAvailableTextToSpeechProfiles
PartyLocalChatControl::SetTextToSpeechProfile
PartyLocalChatControl::GetTextToSpeechProfile
PartyLocalChatControl::GetAvailableTextToSpeechProfiles
5/24/2022 • 2 minutes to read • Edit Online

Gets the text to speech profiles for this chat control.

Syntax
PartyError GetAvailableTextToSpeechProfiles(
uint32_t* profileCount,
PartyTextToSpeechProfileArray* profiles
)

Parameters
profileCount uint32_t*
output
The output number of available profiles.
profiles PartyTextToSpeechProfileArray*
library-allocated output array of size *profileCount
A library-allocated output array containing the available profiles.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
This method synchronously returns the result cached by the last successful
PopulateAvailableTextToSpeechProfiles() operation.

The returned array is only valid until the next call to PartyManager::StartProcessingStateChanges().

Requirements
Header : Party.h

See also
PartyLocalChatControl
PartyLocalChatControl::PopulateAvailableTextToSpeechProfiles
PartyLocalChatControl::SetTextToSpeechProfile
5/24/2022 • 2 minutes to read • Edit Online

Configures the profile to use for a specified type of text-to-speech operation.

Syntax
PartyError SetTextToSpeechProfile(
PartySynthesizeTextToSpeechType type,
PartyString profileIdentifier,
void* asyncIdentifier
)

Parameters
type PartySynthesizeTextToSpeechType

The type of text-to-speech operations for which the specified profile should be used.
profileIdentifier PartyString
The identifier of the profile that text-to-speech operations of the specified type should use.
asyncIdentifier void*
optional
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
Return value
PartyError
c_partyErrorSuccess if the asynchronous operation to set the text to speech profile began, or an error code
otherwise. If this method fails, no related state changes will be generated. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
The profile provided will be used for all subsequent calls to SynthesizeTextToSpeech() that specify the same
value for type . No profile will be configured until SetTextToSpeechProfile() is called at least once. Thus, this
method must be called at least once before any calls to SynthesizeTextToSpeech() can succeed.

This method accepts a profile identifier to indicate the profile selection so that titles may either pass in the result
of PartyTextToSpeechProfile::GetIdentifier() or provide a profile identifier cached from a previous Party library
session.

Multiple SetTextToSpeechProfile() operations can be initiated, and they will be asynchronously queued. Each
operation will be processed and completed in order.

This is an asynchronous operation; a PartySetTextToSpeechProfileCompletedStateChange will be provided via


PartyManager::StartProcessingStateChanges() on completion.
Requirements
Header : Party.h

See also
PartyLocalChatControl
PartyLocalChatControl::GetTextToSpeechProfile
PartyLocalChatControl::GetTextToSpeechProfile
5/24/2022 • 2 minutes to read • Edit Online

Gets the profile that was last configured from a successfully completed SetTextToSpeechProfile() operation for a
specified type of text-to-speech operation.

Syntax
PartyError GetTextToSpeechProfile(
PartySynthesizeTextToSpeechType type,
PartyTextToSpeechProfile** profile
)

Parameters
type PartySynthesizeTextToSpeechType

The type of text-to-speech operations for which the profile should be retrieved.
profile PartyTextToSpeechProfile**
library-allocated output, may return nullptr
The output profile. The profile may be nullptr if none has been set for the specified type. The pointer is only valid
until the next call to PartyManager::StartProcessingStateChanges().
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
If no profile has been successfully configured for the specified type of text-to-speech operation, the retrieved
profile will be null.

The retrieved profile will update when a PartySetTextToSpeechProfileCompletedStateChange associated with a


call to SetTextToSpeechProfile(), which specified the same value for type , is provided via
PartyManager::StartProcessingStateChanges().

Requirements
Header : Party.h

See also
PartyLocalChatControl
PartyLocalChatControl::SetTextToSpeechProfile
PartyLocalChatControl::SynthesizeTextToSpeech
5/24/2022 • 2 minutes to read • Edit Online

Generates text-to-speech audio that is used to either displace the microphone audio associated with this chat
control or render directly to the chat control's audio output.

Syntax
PartyError SynthesizeTextToSpeech(
PartySynthesizeTextToSpeechType type,
PartyString textToSynthesize,
void* asyncIdentifier
)

Parameters
type PartySynthesizeTextToSpeechType

The type of text-to-speech operation.


textToSynthesize PartyString
The text from which to synthesize audio.
asyncIdentifier void*
optional
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
Return value
PartyError
c_partyErrorSuccess if the asynchronous operation to synthesize the text to speech began, or an error code
otherwise. If this method fails, no related state changes will be generated. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
SynthesizeTextToSpeech() cannot be called for a particular type until a text-to-speech profile has been
configured for the specified type via SetTextToSpeechProfile().

SynthesizeTextToSpeech() can be called immediately after configuring a text-to-speech profile via a call to
SetTextToSpeechProfile() with the same type . In such a case, the text-to-speech operation will be queued behind
the completion of the SetTextToSpeechProfile() operation.

Requirements
Header : Party.h

See also
PartyLocalChatControl
PartyLocalChatControl::SetTextToSpeechProfile
PartyLocalChatControl::GetLanguage
5/24/2022 • 2 minutes to read • Edit Online

Gets the language associated with this chat control.

Syntax
PartyError GetLanguage(
PartyString* languageCode
)

Parameters
languageCode PartyString*
library-allocated output
The output BCP 47 language code used by the chat control future communication. The memory for the string
remains valid until the chat control is destroyed.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
The language is used as the spoken language associated with this chat control for transcription and the target
language for incoming translations. If the language code specified is en-US, for instance, the input audio to this
chat control will be treated as the English (United States) language and transcribed as such. If translation is
enabled via either SetTranscriptionOptions() or SetTextChatOptions(), the incoming voice chat transcriptions
and/or text chat will be translated to English (United States).

The language code should be in BCP 47 format; supported language codes are enumerated at
https://docs.microsoft.com/azure/cognitive-services/speech-service/language-support. Specifying an
unsupported or invalid language code will not cause this method to fail, but will result in failure to generate
transcriptions associated with this chat control. The language code can be queried via GetLanguage().

Requirements
Header : Party.h

See also
PartyLocalChatControl
PartyLocalDevice::CreateChatControl
PartyLocalChatControl::SetTranscriptionOptions
PartyLocalChatControl::SetTranscriptionOptions
5/24/2022 • 2 minutes to read • Edit Online

Configures the transcription options associated with voice chat audio for this chat control.

Syntax
PartyError SetTranscriptionOptions(
PartyVoiceChatTranscriptionOptions options,
void* asyncIdentifier
)

Parameters
options PartyVoiceChatTranscriptionOptions

Options associated with voice chat transcription, such as which chat controls should generate transcriptions for
the local chat control, and whether those transcriptions should be translated to the local chat control's language.
asyncIdentifier void*
optional
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
Return value
PartyError
c_partyErrorSuccess if the asynchronous operation to set the transcription options began, or an error code
otherwise. If this method fails, no related state changes will be generated. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
Transcription is the process of generating strings representing spoken phrases in voice chat. The options
specified via options specify the chat controls that should generate these transcription strings, which are
subsequently provided to the local chat control via PartyVoiceChatTranscriptionReceivedStateChanges.

Only chat controls configured to use a language that supports transcription, via
PartyLocalDevice::CreateChatControl(), will provide transcriptions.

Requirements
Header : Party.h

See also
PartyLocalChatControl
PartyLocalChatControl::GetTranscriptionOptions
5/24/2022 • 2 minutes to read • Edit Online

Provides the transcription options associated with voice chat audio for this chat control.

Syntax
PartyError GetTranscriptionOptions(
PartyVoiceChatTranscriptionOptions* options
)

Parameters
options PartyVoiceChatTranscriptionOptions*
output
Options associated with voice chat transcription, such as whether it should be enabled only for the local chat
control, remote chat controls, or none.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
Transcription is the process of generating strings representing spoken phrases in voice chat. The options
specified via options specify the chat controls that should generate these transcription strings, which are
subsequently provided to the local chat control via PartyVoiceChatTranscriptionReceivedStateChanges.

Only chat controls configured to use a language that supports transcription, via
PartyLocalDevice::CreateChatControl(), will provide transcriptions.

Requirements
Header : Party.h

See also
PartyLocalChatControl
PartyLocalChatControl::SetTextChatOptions
5/24/2022 • 2 minutes to read • Edit Online

Configures the text chat options associated with text chat for this chat control.

Syntax
PartyError SetTextChatOptions(
PartyTextChatOptions options,
void* asyncIdentifier
)

Parameters
options PartyTextChatOptions

Options associated with text chat, such as whether incoming text chat should be translated.
asyncIdentifier void*
optional
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
Return value
PartyError
c_partyErrorSuccess if the asynchronous operation to set the chat text options began, or an error code
otherwise. If this method fails, no related state changes will be generated. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Requirements
Header : Party.h

See also
PartyLocalChatControl
PartyLocalChatControl::GetTextChatOptions
5/24/2022 • 2 minutes to read • Edit Online

Provides the text chat options associated with text chat for this chat control.

Syntax
PartyError GetTextChatOptions(
PartyTextChatOptions* options
)

Parameters
options PartyTextChatOptions*
output
Options associated with text chat.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Requirements
Header : Party.h

See also
PartyLocalChatControl
PartyLocalChatControl::SetAudioRenderVolume
5/24/2022 • 2 minutes to read • Edit Online

Configures the volume setting for audio received from a target chat control that will be used for the local chat
control.

Syntax
PartyError SetAudioRenderVolume(
const PartyChatControl* targetChatControl,
float volume
)

Parameters
targetChatControl PartyChatControl*
The target chat control.
volume float
The volume.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
The volume is a fractional percentage between 0.0 (quietest possible) and 1.0 (the standard chat volume).

This is a local setting that takes effect immediately.

Requirements
Header : Party.h

See also
PartyLocalChatControl
PartyLocalChatControl::GetAudioRenderVolume
5/24/2022 • 2 minutes to read • Edit Online

Provides the volume setting for audio received from a target chat control that will be used for the local chat
control.

Syntax
PartyError GetAudioRenderVolume(
const PartyChatControl* targetChatControl,
float* volume
)

Parameters
targetChatControl PartyChatControl*
The target chat control.
volume float*
output
The volume.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
The volume is a fractional percentage between 0.0 (quietest possible) and 1.0 (the standard chat volume).

This is a local setting that takes effect immediately.

Requirements
Header : Party.h

See also
PartyLocalChatControl
PartyLocalChatControl::SetAudioInputMuted
5/24/2022 • 2 minutes to read • Edit Online

Configures whether the user's audio input is in the mute state.

Syntax
PartyError SetAudioInputMuted(
PartyBool muted
)

Parameters
muted PartyBool

True to mute, false otherwise.


Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
Muting determines whether audio data will be captured from the chat control's audio input and sent to the
appropriate chat controls according to the configured relationships. When the audio input is muted, no audio
data will be captured, regardless of the relationships that have been configured. Muting does not stop outgoing
text messages or audio that has been generated by a call to SynthesizeTextToSpeech().

Requirements
Header : Party.h

See also
PartyLocalChatControl
PartyLocalChatControl::GetAudioInputMuted
5/24/2022 • 2 minutes to read • Edit Online

Provides whether the user's audio input is in the mute state.

Syntax
PartyError GetAudioInputMuted(
PartyBool* muted
)

Parameters
muted PartyBool*
output
True if muted, false otherwise.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
Muting determines whether audio data will be captured from the chat control's audio input and sent to the
appropriate chat controls according to the configured relationships. When the audio input is muted, no audio
data will be captured, regardless of the relationships that have been configured. Muting does not stop outgoing
text messages or audio that has been generated by a call to SynthesizeTextToSpeech().

Requirements
Header : Party.h

See also
PartyLocalChatControl
PartyLocalChatControl::SetIncomingAudioMuted
5/24/2022 • 2 minutes to read • Edit Online

Configures whether the incoming audio from the target chat control, in relation to the local chat control, is
muted.

Syntax
PartyError SetIncomingAudioMuted(
const PartyChatControl* targetChatControl,
PartyBool muted
)

Parameters
targetChatControl PartyChatControl*
The target chat control.
muted PartyBool
True to mute, false otherwise.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
Audio muting determines whether incoming voice audio from the target chat control will be rendered to the
local chat control.

Requirements
Header : Party.h

See also
PartyLocalChatControl
PartyLocalChatControl::GetIncomingAudioMuted
5/24/2022 • 2 minutes to read • Edit Online

Provides whether the incoming audio from the target chat control, in relation to the local chat control, has
previously been muted.

Syntax
PartyError GetIncomingAudioMuted(
const PartyChatControl* targetChatControl,
PartyBool* muted
)

Parameters
targetChatControl PartyChatControl*
The target chat control.
muted PartyBool*
output
True if muted, false otherwise.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
Audio muting determines whether incoming voice audio from the target chat control will be rendered to the
local chat control.

Requirements
Header : Party.h

See also
PartyLocalChatControl
PartyLocalChatControl::SetIncomingTextMuted
5/24/2022 • 2 minutes to read • Edit Online

Configures whether the incoming text messages from the target chat control, in relation to the local chat control,
is muted.

Syntax
PartyError SetIncomingTextMuted(
const PartyChatControl* targetChatControl,
PartyBool muted
)

Parameters
targetChatControl PartyChatControl*
The target chat control.
muted PartyBool
True to mute, false otherwise.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
Chat text muting determines whether incoming chat text messages from the target chat control will be provided
to the local chat control.

Requirements
Header : Party.h

See also
PartyLocalChatControl
PartyLocalChatControl::GetIncomingTextMuted
5/24/2022 • 2 minutes to read • Edit Online

Provides whether the incoming text messages from the target chat control, in relation to the local chat control,
has previously been muted.

Syntax
PartyError GetIncomingTextMuted(
const PartyChatControl* targetChatControl,
PartyBool* muted
)

Parameters
targetChatControl PartyChatControl*
The target chat control.
muted PartyBool*
output
True if muted, false otherwise.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
Chat text muting determines whether incoming chat text messages from the target chat control will be provided
to the local chat control.

Requirements
Header : Party.h

See also
PartyLocalChatControl
PartyLocalChatControl::GetLocalChatIndicator
5/24/2022 • 2 minutes to read • Edit Online

Provides a chat indicator specifying the audio state of the local chat control.

Syntax
PartyError GetLocalChatIndicator(
PartyLocalChatControlChatIndicator* chatIndicator
)

Parameters
chatIndicator PartyLocalChatControlChatIndicator*
output
The chat indicator.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
This indicator is intended to assist UI iconic representation so that users can determine whether their voice
audio is being captured and, if not, then why not.

This value changes frequently and is typically polled every graphics frame.

Requirements
Header : Party.h

See also
PartyLocalChatControl
PartyLocalChatControl::GetChatIndicator
5/24/2022 • 2 minutes to read • Edit Online

Provides a chat indicator specifying the audio state of a target chat control in relation to the local chat control.

Syntax
PartyError GetChatIndicator(
const PartyChatControl* targetChatControl,
PartyChatControlChatIndicator* chatIndicator
)

Parameters
targetChatControl PartyChatControl*
The target chat control.
chatIndicator PartyChatControlChatIndicator*
output
The chat indicator.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
This indicator is intended to assist UI iconic representation so that users can determine why they're hearing/
seeing what they are ("who's that talking?"), or why not.

This value changes frequently and is typically polled every graphics frame.

Requirements
Header : Party.h

See also
PartyLocalChatControl
PartyLocalChatControl::ConfigureAudioManipulationCaptureStream
5/24/2022 • 2 minutes to read • Edit Online

Queues an asynchronous operation to configure the audio manipulation capture stream.

Syntax
PartyError ConfigureAudioManipulationCaptureStream(
PartyAudioManipulationSinkStreamConfiguration* configuration,
void* asyncIdentifier
)

Parameters
configuration PartyAudioManipulationSinkStreamConfiguration*
optional
The stream configuration.
asyncIdentifier void*
optional
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
If the configuration is non-null, a capture stream will be created for this chat control. Such a stream acts as the
voice input for this chat control that is sent to all other chat controls to which this chat control is configured to
communicate. If the configuration is null, and a capture stream has previously been configured, the capture will
be destroyed.

Upon completion of the asynchronous operation, when a non-null configuration was specified, a capture stream
for this chat control can be queried via PartyLocalChatControl::GetAudioManipulationCaptureStream().
Completion is indicated by a PartyConfigureAudioManipulationCaptureStreamCompletedStateChange.
Platform support and supported formats
This function is only supported on Windows and Xbox. Calls on other platforms will fail.

The following format options are supported.

F O RM AT O P T IO N SUP P O RT ED VA L UE

Samples per second 24 kHz

Channel mask 0

Channel count 1

Bits per sample 32

Sample type PartyAudioSampleType::Float

Interleaved false
Requirements
Header : Party.h

See also
PartyLocalChatControl
PartyLocalChatControl::GetAudioManipulationCaptureStream
5/24/2022 • 2 minutes to read • Edit Online

Retrieves the audio manipulation capture stream associated with this chat control.

Syntax
PartyError GetAudioManipulationCaptureStream(
PartyAudioManipulationSinkStream** stream
)

Parameters
stream PartyAudioManipulationSinkStream**
library-allocated output
The output stream.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
This stream represents acts as the associated chat control's audio input, i.e. the audio that will be treated as the
local chat control's voice and sent to other chat controls. Typically, the app will retrieve audio from the voice
manipulation stream stream via PartyAudioManipulationSourceStream::GetNextBuffer(), process the audio using
app logic, and then submit the audio back to the library via this stream.

Audio that is submitted to this stream via PartyAudioManipulationSinkStream::SubmitBuffer() will be transcribed


via speech-to-text, if transcription options configured via PartyLocalChatControl::SetTranscriptionOptions
indicates that audio associated the sink's chat control should be.

Requirements
Header : Party.h

See also
PartyLocalChatControl
PartyLocalChatControl::ConfigureAudioManipulationRenderStream
5/24/2022 • 2 minutes to read • Edit Online

Queues an asynchronous operation to configure the audio manipulation render stream.

Syntax
PartyError ConfigureAudioManipulationRenderStream(
PartyAudioManipulationSinkStreamConfiguration* configuration,
void* asyncIdentifier
)

Parameters
configuration PartyAudioManipulationSinkStreamConfiguration*
optional
The stream configuration.
asyncIdentifier void*
optional
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
If the configuration is non-null, an audio manipulation render stream will be created for this chat control. Such a
stream acts as the render pipeline for audio that will be rendered to this chat control. If the configuration is null,
and a stream has previously been configured, the stream will be destroyed.

Upon completion of the asynchronous operation, when a non-null configuration was specified, a render stream
for this chat control can be queried via PartyLocalChatControl::GetAudioManipulationRenderStream().
Completion is indicated by a PartyConfigureAudioManipulationRenderStreamCompletedStateChange.
Platform support and supported formats
This function is only supported on Windows and Xbox. Calls on other platforms will fail.

The following format options are supported.

F O RM AT O P T IO N SUP P O RT ED VA L UE( S)

Samples per second Any value between 8 kHz and 48 kHz, inclusive.

Channel mask Any value

Channel count Any value between 1 and 64, inclusive.

Bits per sample If sample type is PartyAudioSampleType::Float , 32. If


sample type is PartyAudioSampleType::Integer , 16 or 32.

Sample type PartyAudioSampleType::Float or


PartyAudioSampleType::Integer
F O RM AT O P T IO N SUP P O RT ED VA L UE( S)

Interleaved true or false

Requirements
Header : Party.h

See also
PartyLocalChatControl
PartyLocalChatControl::GetAudioManipulationRenderStream
5/24/2022 • 2 minutes to read • Edit Online

Retrieves the manipulation render stream associated with this chat control.

Syntax
PartyError GetAudioManipulationRenderStream(
PartyAudioManipulationSinkStream** stream
)

Parameters
stream PartyAudioManipulationSinkStream**
library-allocated output
The output stream.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
This stream represents the audio that will be rendered to the chat control's audio output. Typically, the app will
retrieve audio from the voice streams associated with all remote chat controls via
PartyAudioManipulationSourceStream::GetNextBuffer(), process and mix each buffer into a single audio stream,
and then submit the mixed stream to be rendered by each appropriate render stream. Each render stream can
be retrieved via PartyLocalChatControl::GetAudioManipulationRenderStream().

Requirements
Header : Party.h

See also
PartyLocalChatControl
PartyLocalDevice
5/24/2022 • 2 minutes to read • Edit Online

Represents the local device.

Syntax
class PartyLocalDevice : public PartyDevice

Public Methods
NAME DESC RIP T IO N

CreateChatControl Queues an asynchronous operation to create a local chat


control for the specified user.

DestroyChatControl Queues an asynchronous operation to destroy a local chat


control.

Requirements
Header : Party.h

See also
Party members
PartyDevice
PartyManager::GetLocalDevice
PartyLocalDevice::CreateChatControl
5/24/2022 • 2 minutes to read • Edit Online

Queues an asynchronous operation to create a local chat control for the specified user.

Syntax
PartyError CreateChatControl(
const PartyLocalUser* localUser,
PartyString languageCode,
void* asyncIdentifier,
PartyLocalChatControl** localChatControl
)

Parameters
localUser PartyLocalUser*
The local user for the new local chat control.
languageCode PartyString
optional
The optional language to use.
asyncIdentifier void*
optional
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
localChatControl PartyLocalChatControl**
optional, library-allocated output
The optional, output local chat control.
Return value
PartyError
c_partyErrorSuccess if the asynchronous operation to create a chat control began, or an error code otherwise. If
this method fails, no related state changes will be generated. The human-readable form of the error code can be
retrieved via PartyManager::GetErrorMessage().

Remarks
If this method returns success, a PartyCreateChatControlCompletedStateChange will be generated to provide
the result of the asynchronous operation. If the asynchronous operation succeeds, a
PartyChatControlCreatedStateChange will be generated. If the operation fails, a
PartyChatControlDestroyedStateChange will be generated. This method itself does not make the chat control
visible to any remote devices. To announce this chat control to remote devices, the title should call
PartyNetwork::ConnectChatControl().

On successful return, this method invalidates the memory for any array previously returned by
PartyManager::GetChatControls() or PartyDevice::GetChatControls() for the local device, as it synchronously
adds the new chat control to the arrays. PartyManager::StartProcessingStateChanges() also invalidates the
memory for these arrays. The returned localChatControl object will be valid until a
PartyChatControlDestroyedStateChange has been generated and all state changes referencing the object have
been returned to PartyManager::FinishProcessingStateChanges().

The language associated with this chat control can optionally be specified via the languageCode parameter. If no
language is specified, the user's default, as determined by the platform, will be used. The language is used as the
spoken the language associated with this chat control for transcription and the target language for incoming
translations. If the language code specified is en-US, for instance, the input audio to this chat control will be
treated as the English (United States) language and transcribed as such. If translation is enabled via either
PartyLocalChatControl::SetTranscriptionOptions() or PartyLocalChatControl::SetTextChatOptions(), the incoming
voice chat transcriptions and/or text chat will be translated to English (United States).

The language code should be in BCP 47 format; supported language codes are enumerated at
https://docs.microsoft.com/azure/cognitive-services/speech-service/language-support. Specifying an
unsupported or invalid language code will not cause this method to fail, but will result in failure to generate
transcriptions associated with this chat control. The language code used with this method can be queried via
PartyLocalChatControl::GetLanguage().

Requirements
Header : Party.h

See also
PartyLocalDevice
PartyCreateChatControlCompletedStateChange
PartyChatControlCreatedStateChange
PartyChatControlDestroyedStateChange
PartyManager::GetChatControls
PartyDevice::GetChatControls
PartyNetwork::ConnectChatControl
PartyLocalChatControl::GetLanguage
PartyLocalChatControl::SetTranscriptionOptions
PartyLocalChatControl::SetTranscriptionOptions
PartyLocalDevice::DestroyChatControl
5/24/2022 • 2 minutes to read • Edit Online

Queues an asynchronous operation to destroy a local chat control.

Syntax
PartyError DestroyChatControl(
PartyLocalChatControl* localChatControl,
void* asyncIdentifier
)

Parameters
localChatControl PartyLocalChatControl*
The local chat control to destroy.
asyncIdentifier void*
optional
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
Return value
PartyError
c_partyErrorSuccess if the asynchronous operation to destroy the chat control began, or an error code
otherwise. If this method fails, no related state changes will be generated. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
This method queues an asynchronous attempt to destroy a local chat control. A
PartyDestroyChatControlCompletedStateChange will be provided upon completion of the operation, indicating
success or failure. Before successful completion of the operation, the local chat control will be disconnected from
all networks it was previously connected to (each indicated by a PartyChatControlLeftNetworkStateChange).
Memory for the local chat control will remain valid until all state changes referencing the chat control have been
returned to PartyManager::FinishProcessingStateChanges().

Requirements
Header : Party.h

See also
PartyLocalDevice
PartyDestroyChatControlCompletedStateChange
PartyChatControlDestroyedStateChange
PartyChatControlLeftNetworkStateChange
PartyLocalEndpoint
5/24/2022 • 2 minutes to read • Edit Online

Represents a local endpoint.

Syntax
class PartyLocalEndpoint : public PartyEndpoint

Public Methods
NAME DESC RIP T IO N

GetLocalUser Gets the local user associated with this local endpoint.

SendMessage Sends a message to other endpoints in the network.

FlushMessages Forces all queued messages to the specified endpoints from


this local endpoint to be sent as soon as possible regardless
of their coalesce settings.

GetEndpointStatistics Gets one or more statistic counter values for the specified
target endpoints.

Requirements
Header : Party.h

See also
Party members
PartyEndpoint
PartyEndpoint::GetLocal
PartyLocalEndpoint::GetLocalUser
5/24/2022 • 2 minutes to read • Edit Online

Gets the local user associated with this local endpoint.

Syntax
PartyError GetLocalUser(
PartyLocalUser** localUser
)

Parameters
localUser PartyLocalUser**
library-allocated output, may return nullptr
The output local user associated with this local endpoint, or nullptr.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
If this endpoint is not associated with a user, localUser is set to nullptr.

Requirements
Header : Party.h

See also
PartyLocalEndpoint
PartyLocalEndpoint::SendMessage
5/24/2022 • 5 minutes to read • Edit Online

Sends a message to other endpoints in the network.

Syntax
PartyError SendMessage(
uint32_t targetEndpointCount,
PartyEndpointArray targetEndpoints,
PartySendMessageOptions options,
const PartySendMessageQueuingConfiguration* queuingConfiguration,
uint32_t dataBufferCount,
const PartyDataBuffer* dataBuffers,
void* messageIdentifier
)

Parameters
targetEndpointCount uint32_t
The number of target endpoints in the targetEndpoints array. May be zero to broadcast to all remote endpoints
in the network. A device that receives a broadcast message will have the target endpoint fields of the
PartyEndpointMessageReceivedStateChange populated with all of the device's local endpoints.
targetEndpoints PartyEndpointArray
input array of size targetEndpointCount

The targetEndpointCount entry array of target PartyEndpoint object pointers to which the message should be
sent. This is ignored when targetEndpointCount is zero.
options PartySendMessageOptions
Zero or more option flags describing how to send the message.
queuingConfiguration PartySendMessageQueuingConfiguration*
optional
An optional structure describing how the message should behave while locally queued and waiting for an
opportunity to transmit. May be nullptr to use default queuing behavior.
dataBufferCount uint32_t
The number of buffer structures provided in the dataBuffers array. Must be greater than 0.
dataBuffers PartyDataBuffer*
input array of size dataBufferCount
The dataBufferCount entry array of PartyDataBuffer structures describing the message payload to send.
messageIdentifier void*
optional
An opaque, caller-specific context pointer the Party library will include in any state changes referring to this
message. It is not interpreted or transmitted remotely. May be nullptr if no message identification context is
needed.
Return value
PartyError
c_partyErrorSuccess if enqueuing the message for transmission succeeded or an error code otherwise. If this
method fails, no related state changes will be generated. The human-readable form of the error code can be
retrieved via PartyManager::GetErrorMessage().

Remarks
Sending messages to local endpoints is not currently supported. If the array of target endpoints includes any
local targets, this call will synchronously fail.

All targeted endpoints on a given device will be provided a single PartyEndpointMessageReceivedStateChange


with every targeted local endpoint provided in the PartyEndpointMessageReceivedStateChange
receiverEndpoints array.

If the array of target endpoints is specified as having zero entries, then the message is broadcast to all remote
endpoints currently in the network.

Callers provide 1 or more PartyDataBuffer structures in the dataBuffers array. The memory that the structures
reference does not have to be contiguous, making it easy to have a fixed header buffer followed by a variable
payload, for example. The buffers will be assembled in order, transmitted, and delivered to the targeted
endpoints as a single contiguous data block in a PartyEndpointMessageReceivedStateChange. The Party library
does not expend bandwidth transmitting metadata to describe the original PartyDataBuffer segmentation.

By default, the buffers described in the caller's dataBuffers array are copied to an allocated buffer before
SendMessage() returns. Specifying PartySendMessageOptions::DontCopyDataBuffers will avoid this extra copy
step and instead require the caller to keep the memory specified in each buffer valid and unmodified until a
PartyDataBuffersReturnedStateChange returns ownership of the memory to the caller. The PartyDataBuffer
structures themselves do not need to remain valid after the SendMessage() call returns, only the memory that
they reference.

Callers that use PartySendMessageOptions::DontCopyDataBuffers may provide a caller-specific


messageIdentifier context. This pointer-sized value will be included with all
PartyDataBuffersReturnedStateChanges so that the caller can easily access its own private message tracking
information. The actual value is treated as opaque and is not interpreted by the Party library, nor transmitted
remotely. It's the caller's responsibility to ensure any of its own memory that messageIdentifier might
represent remains valid until the final requested state change associated with the message and associated
messageIdentifier has been processed and returned via PartyManager::FinishProcessingStateChanges().

Messages may not be transmitted to target endpoints right away based on factors such as connection quality
and receiver responsiveness. The local send queue will grow if you are sending faster than the connection to an
endpoint is estimated to currently support. This increases memory usage and may result in increases in
perceived message latency, so callers are strongly recommended to monitor and manage the local send queues.
You can retrieve information about the send queue using PartyLocalEndpoint::GetEndpointStatistics(). You can
manage the send queue by reducing the size and/or frequency of sending, by using the queuingConfiguration
optional settings to configure timeouts that automatically expire messages that have been queued for too long,
or by using PartyLocalEndpoint::CancelMessages() to explicitly remove some or all queued messages.

When this method returns success, the message has begun transmitting or has successfully been enqueued for
future transmission. In particular, a successful return from this method does not imply that the message was
successfully delivered to any recipients. The Party API does not currently provide a way to track the delivery and
processing of individual messages. The PartyNetwork::GetNetworkStatistics() and GetEndpointStatistics()
methods can be used to query aggregate statistics for the network as a whole or for an individual local
endpoint, respectively.

If options includes PartySendMessageOptions::GuaranteedDelivery and the message could not be successfully


delivered to the transparent cloud relay server for forwarding to the target endpoints, then a
PartyNetworkDestroyedStateChange will be generated. In other words, messages with a guaranteed delivery
requirement will either be delivered or the sending client will be disconnected from the network. When the
transparent cloud relay server forwards the guaranteed delivery message to each remote device containing one
or more target endpoints, if the message could not be delivered, the remote device will likewise be disconnected
from the network, indicated by a PartyNetworkDestroyedStateChange. In other words, a device that fails to
receive a message with a guaranteed delivery requirement will be disconnected from the network.

The Party library automatically fragments and reassembles large messages that exceed the maximum size
supported by the environment so that callers are not required to manage this. However, there is a small amount
of overhead associated with fragmentation. Callers that are able to send smaller messages or otherwise
naturally break up large state payloads efficiently themselves may wish to do so.

If SendMessage() is invoked with a zero entry target endpoint array prior to successfully authenticating a first
user into the network, then even though no remote endpoints have been reported via
PartyEndpointCreatedStateChange state changes (and therefore known to exist in the network), the message will
still be queued. Once the first user has successfully authenticated and this sending local endpoint has been
successfully created, the queued message will then target all remote endpoints that exist in the network at that
later time. Because the future state of the network and the set of ultimately receiving endpoints isn't known at
SendMessage() time in this case, titles should exercise caution regarding what content is placed in such deferred
broadcast messages, or simply refrain from submitting them at all until this local device and endpoint are fully
participating in the network.

Requirements
Header : Party.h

See also
PartyLocalEndpoint
PartySendMessageOptions
PartySendMessageQueuingConfiguration
PartyDataBuffersReturnedStateChange
PartyEndpointMessageReceivedStateChange
PartyNetwork::GetNetworkStatistics
PartyLocalEndpoint::GetEndpointStatistics
PartyLocalEndpoint::FlushMessages
PartyLocalEndpoint::FlushMessages
5/24/2022 • 2 minutes to read • Edit Online

Forces all queued messages to the specified endpoints from this local endpoint to be sent as soon as possible
regardless of their coalesce settings.

Syntax
PartyError FlushMessages(
uint32_t targetEndpointCount,
PartyEndpointArray targetEndpoints
)

Parameters
targetEndpointCount uint32_t
This parameter is currently ignored. The number of target endpoints in the targetEndpoints array.
targetEndpoints PartyEndpointArray
input array of size targetEndpointCount

This parameter is currently ignored. A targetEndpointCount entry array of target PartyEndpoint object pointers.
Messages from this local endpoint, up through and including the most recent message to any endpoint in the
array, will be transmitted as soon as possible.
Return value
PartyError
c_partyErrorSuccess if flushing messages succeeded or an error code otherwise. The human-readable form of
the error code can be retrieved via PartyManager::GetErrorMessage().

Remarks
When PartySendMessageOptions::CoalesceOpportunistically or
PartySendMessageOptions::AlwaysCoalesceUntilFlushed is specified in a call to SendMessage(), the message
may not be transmitted immediately and instead be combined with other messages. This coalescing can
improve bandwidth efficiency at the potential expense of perceived latency. This method allows the title to
manually force such coalesced messages to begin transmitting as soon as possible.

Currently this method ignores the targetEndpoints parameter and forces all queued messages from this local
endpoint to be transmitted as soon as possible.

Requirements
Header : Party.h

See also
PartyLocalEndpoint
PartyLocalEndpoint::SendMessage
PartySendMessageOptions
PartyLocalEndpoint::GetEndpointStatistics
5/24/2022 • 2 minutes to read • Edit Online

Gets one or more statistic counter values for the specified target endpoints.

Syntax
PartyError GetEndpointStatistics(
uint32_t targetEndpointCount,
PartyEndpointArray targetEndpoints,
uint32_t statisticCount,
const PartyEndpointStatistic* statisticTypes,
uint64_t* statisticValues
)

Parameters
targetEndpointCount uint32_t
The number of target endpoints in the targetEndpoints array. May be 0 to retrieve statistics for all endpoints
currently in the network, including this local one.
targetEndpoints PartyEndpointArray
input array of size targetEndpointCount

The targetEndpointCount entry array of target PartyEndpoint object pointers for which statistics should be
retrieved. This is ignored when targetEndpointCount is zero.
statisticCount uint32_t
The number of statistics in the input statisticTypes array and to be written in the statisticValues output
array. This must be at least 1.
statisticTypes PartyEndpointStatistic*
input array of size statisticCount
The statisticCount entry input array of unique PartyEndpointStatistic types to retrieve.
statisticValues uint64_t*
output array of size statisticCount
The statisticCount entry output array where the statistic values should be written. Each statistic value will be
written at the same entry index corresponding to where the requested PartyEndpointStatistic appears in the
statisticTypes input array.

Return value
PartyError
c_partyErrorSuccess if retrieving the endpoint statistics succeeded or an error code otherwise. The human-
readable form of the error code can be retrieved via PartyManager::GetErrorMessage().

Remarks
This method is used to retrieve performance counters, queue lengths, historical usage metrics, or other
statistical information recorded between this local endpoint and a target endpoint.

Alternatively, multiple target endpoints can be provided, or a zero-entry array to retrieve statistics for all target
endpoints currently in the network, including this local one. If multiple target endpoints are requested, then the
values returned are the combined statistics for those endpoints. The particular method used to combine
multiple endpoint statistics into a single value depends on and is described by the specific PartyEndpointStatistic
type.

A given PartyEndpointStatistic type may appear in any order in the statisticTypes array, but must not be
specified more than once. Each corresponding statistic value will be written to the statisticValues array in the
same order.

The returned statistic values are always the most current ones available. There is no guarantee they will report
the same value from one GetEndpointStatistics() call to the next, even if there were no intervening calls to
PartyManager::StartProcessingStateChanges() or PartyManager::FinishProcessingStateChanges().

Requirements
Header : Party.h

See also
PartyLocalEndpoint
PartyEndpointStatistic
PartyNetwork::GetNetworkStatistics
PartyLocalUser
5/24/2022 • 2 minutes to read • Edit Online

Represents a local user.

Syntax
class PartyLocalUser

Public Methods
NAME DESC RIP T IO N

GetEntityId Gets the Entity ID associated with this local user.

UpdateEntityToken Updates the PlayFab Entity Token associated with this local
user, for use in future authenticated operations.

GetCustomContext Retrieves the app's private, custom pointer-sized context


value previously associated with this local user object.

SetCustomContext Configures an optional, custom pointer-sized context value


with this local user object.

Requirements
Header : Party.h

See also
Party members
PartyManager::CreateLocalUser
PartyManager::GetLocalUsers
PartyManager::DestroyLocalUser
PartyManager::CreateNewNetwork
PartyNetwork::AuthenticateLocalUser
PartyNetwork::RemoveLocalUser
PartyNetwork::CreateInvitation
PartyNetwork::RevokeInvitation
PartyNetwork::CreateEndpoint
PartyLocalDevice::CreateChatControl
PartyLocalUser::GetEntityId
5/24/2022 • 2 minutes to read • Edit Online

Gets the Entity ID associated with this local user.

Syntax
PartyError GetEntityId(
PartyString* entityId
)

Parameters
entityId PartyString*
library-allocated output
The output Entity ID.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
The retrieved Entity ID is identical to the Entity ID provided by the title via PartyManager::CreateLocalUser().

The memory for the Entity ID string remains valid for the life of the local user, which is until its
PartyDestroyLocalUserCompletedStateChange has been provided via
PartyManager::StartProcessingStateChanges() and all state changes referencing the local user have been
returned to PartyManager::FinishProcessingStateChanges().

Requirements
Header : Party.h

See also
PartyLocalUser
PartyManager::CreateLocalUser
PartyLocalUser::UpdateEntityToken
5/24/2022 • 2 minutes to read • Edit Online

Updates the PlayFab Entity Token associated with this local user, for use in future authenticated operations.

Syntax
PartyError UpdateEntityToken(
PartyString titlePlayerEntityToken
)

Parameters
titlePlayerEntityToken PartyString
The PlayFab Entity Token to associate with the local user.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
This method takes a PlayFab Entity Token as titlePlayerEntityToken . No synchronous validation is performed
on this value. When the library performs operations that require user authentication or authorization, such as
creating a network, authenticating into a network, or performing speech-to-text transcription, the Party service
will validate that the token is valid, is not expired, is associated with the same Entity ID that was provided to the
PartyManager::CreateLocalUser() call, and is authorized to perform the operation. If these conditions aren't met,
the operation will fail.

A PlayFab Entity Token can be obtained from the output of a PlayFab login operation and then provided as input
to this method. The token must be associated with a PlayFab Entity of type title_player_account , which, for
most developers, represents the "player" in the most traditional way.

The provided titlePlayerEntityToken must have been acquired using the same Title ID that was passed to
PartyManager::Initialize().

The Party library makes a copy of the supplied PlayFab Entity Token for use in subsequent operations that
require authentication or authorization of the local user, such as PartyManager::CreateNewNetwork() or
PartyNetwork::AuthenticateLocalUser(). If the token provided to this call is expired or otherwise invalid,
operations that require a valid token will fail. A new, valid token can be provided to the Party library by another
call to this method.

The caller is responsible for monitoring the expiration of the entity token provided to this method and
PartyManager::CreateLocalUser(). When the token is nearing or past the expiration time a new token should be
obtained by performing a PlayFab login operation and provided to the Party library by calling this method. It is
recommended to acquire a new token when the previously supplied token is halfway through its validity period.
On platforms that may enter a low power state or otherwise cause the application to pause execution for a long
time, preventing the token from being refreshed before it expires, the token should be checked for expiration
once execution resumes.

Requirements
Header : Party.h

See also
PartyLocalUser
PartyManager::GetErrorMessage
PartyManager::CreateLocalUser
PartyManager::CreateNewNetwork
PartyNetwork::AuthenticateLocalUser
PartyLocalUser::GetCustomContext
5/24/2022 • 2 minutes to read • Edit Online

Retrieves the app's private, custom pointer-sized context value previously associated with this local user object.

Syntax
PartyError GetCustomContext(
void** customContext
)

Parameters
customContext void**
output, may return nullptr
The output custom context.
Return value
PartyError
c_partyErrorSuccess if retrieving the custom context succeeded or an error code otherwise. The human-
readable form of the error code can be retrieved via PartyManager::GetErrorMessage().

Remarks
If no custom context has been set yet, the value pointed to by customContext is set to nullptr.

Requirements
Header : Party.h

See also
PartyLocalUser
PartyLocalUser::SetCustomContext
PartyLocalUser::SetCustomContext
5/24/2022 • 2 minutes to read • Edit Online

Configures an optional, custom pointer-sized context value with this local user object.

Syntax
PartyError SetCustomContext(
void* customContext
)

Parameters
customContext void*
optional
An arbitrary, pointer-sized value to store with the player object.
Return value
PartyError
c_partyErrorSuccess if configuring the custom context succeeded or an error code otherwise. The human-
readable form of the error code can be retrieved via PartyManager::GetErrorMessage().

Remarks
The custom context is typically used as a "shortcut" that simplifies accessing local, title-specific memory
associated with the local user without requiring a mapping lookup. The value is retrieved using the
GetCustomContext() method.

Any configured value is treated as opaque by the library, and is only valid on the local device; it is not
transmitted over the network.

Requirements
Header : Party.h

See also
PartyLocalUser
PartyLocalUser::GetCustomContext
PartyManager
5/24/2022 • 2 minutes to read • Edit Online

The primary management class for interacting with the Party library.

Syntax
class PartyManager

Public Methods
NAME DESC RIP T IO N

GetSingleton Retrieves a reference to the PartyManager singleton


instance.

SetOption Configures an option to fine-tune Party library functionality.

GetOption Retrieves an option used to fine-tune Party library


functionality.

GetErrorMessage Get the human-readable form of an error.

SerializeNetworkDescriptor Serializes a network descriptor structure into an opaque


string that is safe to communicate over title and platform-
specific communication channels.

DeserializeNetworkDescriptor Deserializes a network descriptor structure from an opaque


string serialized via a prior call to
SerializeNetworkDescriptor().

SetMemoryCallbacks Optionally configures the memory allocation and freeing


callbacks the Party library should use.

GetMemoryCallbacks Retrieves the memory allocation and freeing callbacks the


Party library is using.

SetProfilingCallbacksForMethodEntryExit Optionally configures the profiling event callbacks the Party


library will make when entering or exiting instrumented
methods.

GetProfilingCallbacksForMethodEntryExit Retrieves the profiling event callbacks the Party library is


configured to use when entering or exiting instrumented
methods.

SetThreadAffinityMask Optionally configures the processor on which internal Party


library threads will run.
NAME DESC RIP T IO N

GetThreadAffinityMask Retrieves the current set of processors on which internal


Party library threads will run or are running as an affinity
mask.

SetWorkMode Configures the work mode of the Party library processing


task associated with threadId .

GetWorkMode Retrieves the current work mode of the Party library's


internal processing task associated with threadId .

Initialize Initializes the PartyManager object instance.

Cleanup Immediately reclaims all resources associated with all Party


library objects.

StartProcessingStateChanges Retrieves an array of all PartyStateChanges to process since


the last such call.

FinishProcessingStateChanges Returns an array of PartyStateChanges that were being


processed.

DoWork Synchronously performs the processing task associated with


threadId .

GetRegions Gets an array containing the set of regions for which your
title is configured, along with round trip latency information.

CreateNewNetwork Queues an asynchronous attempt to create a new network.

ConnectToNetwork Queues an asynchronous attempt to connect to a network.

GetLocalDevice Gets the local device.

CreateLocalUser Creates a local user object that is used to represent a local


user when performing networking and chat operations.

DestroyLocalUser Starts an asynchronous operation to destroy a local user.

GetLocalUsers Gets an array containing all local users created by


CreateLocalUser().

GetNetworks Gets an array of all networks to which the local device is


connected or connecting.

GetChatControls Gets an array that contains a combined list of all chat


controls on the local device and all remote devices.

Remarks
Only a single instance of the class is permitted.

Requirements
Header : Party.h

See also
Party members
PartyManager::GetSingleton
5/24/2022 • 2 minutes to read • Edit Online

Retrieves a reference to the PartyManager singleton instance.

Syntax
PartyManager& GetSingleton(
)

Parameters
Return value
PartyManager&
The PartyManager singleton instance.

Requirements
Header : Party.h

See also
PartyManager
PartyManager::SetOption
5/24/2022 • 2 minutes to read • Edit Online

Configures an option to fine-tune Party library functionality.

Syntax
PartyError SetOption(
void* object,
PartyOption option,
const void* value
)

Parameters
object void*
optional
The Party library object that may be required as context for different PartyOption values.
option PartyOption
The Party library option to configure.
value void*
optional
A pointer to the value used to override option . If value is null, the option will be reset to its default value.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise.

Requirements
Header : Party.h

See also
PartyManager
PartyOption
PartyManager::GetOption
PartyManager::GetOption
5/24/2022 • 2 minutes to read • Edit Online

Retrieves an option used to fine-tune Party library functionality.

Syntax
PartyError GetOption(
const void* object,
PartyOption option,
void* value
)

Parameters
object void*
optional
The Party library object that may be required as context for different PartyOption values.
option PartyOption
The Party library option to retrieve.
value void*
output
An output value to fill with the current option setting. If this option has not yet been overridden by a call to
PartyManager::SetOption(), this method will retrieve that option's default value.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise.

Requirements
Header : Party.h

See also
PartyManager
PartyOption
PartyManager::SetOption
PartyManager::GetErrorMessage
5/24/2022 • 2 minutes to read • Edit Online

Get the human-readable form of an error.

Syntax
PartyError GetErrorMessage(
PartyError error,
PartyString* errorMessage
)

Parameters
error PartyError

An error code.
errorMessage PartyString*
library-allocated output
The output, human-readable error message. The memory for the returned string remains valid for the lifetime
of the process.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise.

Remarks
These error messages are not localized and are only intended for developers, i.e. these error messages are not
intended to be shown to users via UI.

Requirements
Header : Party.h

See also
PartyManager
PartyManager::SerializeNetworkDescriptor
5/24/2022 • 2 minutes to read • Edit Online

Serializes a network descriptor structure into an opaque string that is safe to communicate over title and
platform-specific communication channels.

Syntax
PartyError SerializeNetworkDescriptor(
const PartyNetworkDescriptor* networkDescriptor,
char* serializedNetworkDescriptorString
)

Parameters
networkDescriptor PartyNetworkDescriptor*
The network descriptor to serialize.
serializedNetworkDescriptorString char*
output string buffer of size c_maxSerializedNetworkDescriptorStringLength+1

The output buffer to which the serialized network descriptor string is written. The serialized network descriptor
string will never contain non-ASCII, control, or other characters that would require JSON or XML escaping.
Return value
PartyError
c_partyErrorSuccess if the descriptor is serializable and was successfully serialized, or an error code otherwise.

Remarks
A network descriptor contains all the information required for a device to connect to the network to which the
descriptor is associated. serializedNetworkDescriptorString is the serialized form of the descriptor specified by
networkDescriptor and is safe to communicate over title and platform-specific communication channels. The
string may be up to c_maxSerializedNetworkDescriptorStringLength characters long, not including the null
terminator, and will never contain non-ASCII, control, or other characters that would require JSON or XML
escaping.

This method will fail if the network descriptor is not serializable. For example, the descriptor provided
synchronously by a call to CreateNewNetwork() is not serializable because it does not contain enough
information for a remote client to connect to the new network. The network descriptor changes and becomes
serializable when the PartyCreateNewNetworkCompletedStateChange is provided and indicates success. The
updated network descriptor is provided as a field in the PartyCreateNewNetworkCompletedStateChange. Once
connected to the network, the descriptor can be retrieved using PartyNetwork::GetNetworkDescriptor().

PartyNetworkDescriptors work in tandem with PartyInvitations to facilitate inviting remote users to join the
network. First, obtain the network descriptor via PartyNetwork::GetNetworkDescriptor() and serialize it via
SerializeNetworkDescriptor(). Next, create an invitation via PartyNetwork::CreateInvitation() or query for a
preexisting invitation via PartyNetwork::GetInvitations() and obtain the invitation's identifier from its
configuration via PartyInvitation::GetInvitationConfiguration(). Last, include both the serialized network
descriptor and the invitation identifier in the payload of the platform-specific invite mechanism. When the
remote user receives the invite, they deserialize the network descriptor from the platform-invite payload via
DeserializeNetworkDescriptor() and pass the deserialized descriptor to ConnectToNetwork(). After connecting,
the remote user joins by authenticating into the network via PartyNetwork::AuthenticateLocalUser() with the
invitation identifier in the platform-invite payload.

This method can be called prior to the Initialize() method.

Requirements
Header : Party.h

See also
PartyManager
PartyManager::DeserializeNetworkDescriptor
PartyNetwork::GetNetworkDescriptor
PartyManager::ConnectToNetwork
PartyInvitation
PartyNetwork::CreateInvitation
PartyNetwork::GetInvitations
PartyInvitation::GetInvitationConfiguration
PartyNetwork::AuthenticateLocalUser
PartyManager::DeserializeNetworkDescriptor
5/24/2022 • 2 minutes to read • Edit Online

Deserializes a network descriptor structure from an opaque string serialized via a prior call to
SerializeNetworkDescriptor().

Syntax
PartyError DeserializeNetworkDescriptor(
PartyString serializedNetworkDescriptorString,
PartyNetworkDescriptor* networkDescriptor
)

Parameters
serializedNetworkDescriptorString PartyString
The serialized network descriptor string.
networkDescriptor PartyNetworkDescriptor*
output
The output network descriptor. serializedNetworkDescriptorString .
Return value
PartyError
c_partyErrorSuccess if the descriptor string is a valid serialized network descriptor string and was successfully
deserialized, or an error code otherwise.

Remarks
The resulting networkDescriptor can be used to connect to a network via ConnectToNetwork().

This method can be called prior to the Initialize() method.

Requirements
Header : Party.h

See also
PartyManager
PartyManager::SerializeNetworkDescriptor
PartyManager::ConnectToNetwork
PartyManager::SetMemoryCallbacks
5/24/2022 • 2 minutes to read • Edit Online

Optionally configures the memory allocation and freeing callbacks the Party library should use.

Syntax
PartyError SetMemoryCallbacks(
PartyAllocateMemoryCallback allocateMemoryCallback,
PartyFreeMemoryCallback freeMemoryCallback
)

Parameters
allocateMemoryCallback PartyAllocateMemoryCallback
A pointer to the custom allocation callback to use.
freeMemoryCallback PartyFreeMemoryCallback
A pointer to the custom freeing callback to use.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via GetErrorMessage().

Remarks
This method allows the title to install custom memory allocation functions in order to service all requests by the
Party library for new memory buffers instead of using its default allocation functions.

The allocateMemoryCallback and freeMemoryCallback parameters must both be non-null.

To use this method, it must be called before any other Party method except for
PartyManager::GetMemoryCallbacks(). This method cannot be called again for the lifetime of this process.

Requirements
Header : Party.h

See also
PartyManager
PartyAllocateMemoryCallback
PartyFreeMemoryCallback
PartyManager::GetMemoryCallbacks
PartyManager::GetMemoryCallbacks
5/24/2022 • 2 minutes to read • Edit Online

Retrieves the memory allocation and freeing callbacks the Party library is using.

Syntax
PartyError GetMemoryCallbacks(
PartyAllocateMemoryCallback* allocateMemoryCallback,
PartyFreeMemoryCallback* freeMemoryCallback
)

Parameters
allocateMemoryCallback PartyAllocateMemoryCallback*
output
A place to store a pointer to the memory allocation callback currently used.
freeMemoryCallback PartyFreeMemoryCallback*
output
A place to store a pointer to the memory freeing callback currently used.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via GetErrorMessage().

Remarks
This retrieves the memory allocation functions servicing requests by the Party library for new memory.

This method does not require the Initialize() method to have been called first.

Requirements
Header : Party.h

See also
PartyManager
PartyAllocateMemoryCallback
PartyFreeMemoryCallback
PartyManager::SetMemoryCallbacks
PartyManager::SetProfilingCallbacksForMethodEntryExit
5/24/2022 • 2 minutes to read • Edit Online

Optionally configures the profiling event callbacks the Party library will make when entering or exiting
instrumented methods.

Syntax
PartyError SetProfilingCallbacksForMethodEntryExit(
PartyProfilingMethodEntranceCallback profilingMethodEntranceCallback,
PartyProfilingMethodExitCallback profilingMethodExitCallback
)

Parameters
profilingMethodEntranceCallback PartyProfilingMethodEntranceCallback
optional
The callback to be made when the Party library enters an internal method which is instrumented for profiling.
profilingMethodExitCallback PartyProfilingMethodExitCallback
optional
The callback to be made when the Party library is about to exit an internal method which is instrumented for
profiling.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via GetErrorMessage().

Remarks
This method allows the title to install custom profiling callback functions in order to record and visualize Party
library performance metrics in external profiling tools.

This method can only be called when the Party library is uninitialized. Calling while Party is initialized will fail
and return an error.

Setting an optional callback equal to nullptr will cause the Party library to not make any profiling callbacks for
that event type.

In order to minimize the impact of profiling on title performance, callbacks for these events should be kept as
lightweight as possible, as they are expected to fire hundreds or thousands of times per second.

This method is only supported on the Windows, Xbox One XDK, and Microsoft Game Core versions of the
library. Calls on other platforms will fail.

Requirements
Header : Party.h
See also
PartyManager
PartyProfilingMethodEntranceCallback
PartyProfilingMethodExitCallback
PartyManager::GetProfilingCallbacksForMethodEntryExit
PartyManager::GetProfilingCallbacksForMethodEntryExit
5/24/2022 • 2 minutes to read • Edit Online

Retrieves the profiling event callbacks the Party library is configured to use when entering or exiting
instrumented methods.

Syntax
PartyError GetProfilingCallbacksForMethodEntryExit(
PartyProfilingMethodEntranceCallback* profilingMethodEntranceCallback,
PartyProfilingMethodExitCallback* profilingMethodExitCallback
)

Parameters
profilingMethodEntranceCallback PartyProfilingMethodEntranceCallback*
library-allocated output, may return nullptr
A pointer to the callback made when the Party library enters an internal method which is instrumented for
profiling.
profilingMethodExitCallback PartyProfilingMethodExitCallback*
library-allocated output, may return nullptr
A pointer to the callback made when the Party library is about to exit an internal method which is instrumented
for profiling.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via GetErrorMessage().

Remarks
This method retrieves the profiling callback functions the Party library is calling for the instrumented event
types.

A callback equal to nullptr indicates that the Party library will not make any profiling callbacks for that event
type.

This method is only supported on the Windows, Xbox One XDK, and Microsoft Game Core versions of the
library. Calls on other platforms will fail.

Requirements
Header : Party.h

See also
PartyManager
PartyProfilingMethodEntranceCallback
PartyProfilingMethodExitCallback
PartyManager::SetProfilingCallbacksForMethodEntryExit
PartyManager::SetThreadAffinityMask
5/24/2022 • 2 minutes to read • Edit Online

Optionally configures the processor on which internal Party library threads will run.

Syntax
PartyError SetThreadAffinityMask(
PartyThreadId threadId,
uint64_t threadAffinityMask
)

Parameters
threadId PartyThreadId

The type of internal Party library thread to configure processor affinity.


threadAffinityMask uint64_t
The affinity mask for this type of Party library thread.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via GetErrorMessage().

Remarks
This method enables the title to configure the processor affinity for internal Party library threads of a given type.
On Windows, the Audio type affects both library's directly-owned threads and threads owned by XAudio2. For
more information, see PartyThreadId.

This method may be called at any time before or after Initialize() and will take effect immediately. Thread
processor settings are persisted across calls to Cleanup() and Initialize(). When there are more than 64 cores
present, this method always applies to processor group 0.

In order to specify any processor, pass c_anyProcessor as the threadAffinityMask parameter. This is also the
default value the Party library will use if this method is never called.

Requirements
Header : Party.h

See also
PartyManager
PartyThreadId
PartyManager::GetThreadAffinityMask
PartyManager::GetThreadAffinityMask
5/24/2022 • 2 minutes to read • Edit Online

Retrieves the current set of processors on which internal Party library threads will run or are running as an
affinity mask.

Syntax
PartyError GetThreadAffinityMask(
PartyThreadId threadId,
uint64_t* threadAffinityMask
)

Parameters
threadId PartyThreadId

The type of internal Party library thread for which processor affinity should be retrieved.
threadAffinityMask uint64_t*
output
The output affinity mask for this type of Party library thread.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via GetErrorMessage().

Remarks
This retrieves the current processor affinity for internal Party library threads of a given type.

This method does not require Initialize() to have been called first.

A reported value of c_anyProcessor written to threadAffinityMask indicates that the thread is free to run on any
processor.

Requirements
Header : Party.h

See also
PartyManager
PartyThreadId
PartyManager::SetThreadAffinityMask
PartyManager::SetWorkMode
5/24/2022 • 2 minutes to read • Edit Online

Configures the work mode of the Party library processing task associated with threadId .

Syntax
PartyError SetWorkMode(
PartyThreadId threadId,
PartyWorkMode workMode
)

Parameters
threadId PartyThreadId

A high-level categorization of the Party library's internal processing task.


workMode PartyWorkMode
The target work mode for the associated processing task.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via GetErrorMessage().

Remarks
If the work mode is set as PartyWorkMode::Automatic, the processing task associated with threadId is handled
internally by the Party library. If the work mode is configured as PartyWorkMode::Manual, the title must instead
perform the processing task associated with threadId via periodic calls to DoWork().

This method can only be called when the Party library is uninitialized. Calling while initialized will fail and return
an error.

Configuration of the work mode associated with threadId persists across subsequent calls to Cleanup() and
Initialize().

Requirements
Header : Party.h

See also
PartyManager
PartyManager::GetWorkMode
PartyManager::DoWork
PartyManager::GetWorkMode
5/24/2022 • 2 minutes to read • Edit Online

Retrieves the current work mode of the Party library's internal processing task associated with threadId .

Syntax
PartyError GetWorkMode(
PartyThreadId threadId,
PartyWorkMode* workMode
)

Parameters
threadId PartyThreadId

A high-level categorization of the Party library's internal processing task.


workMode PartyWorkMode*
output
The current work mode for the associated processing task.
Return value
PartyError
c_partyErrorSuccess

Requirements
Header : Party.h

See also
PartyManager
PartyManager::SetWorkMode
PartyManager::DoWork
PartyManager::Initialize
5/24/2022 • 2 minutes to read • Edit Online

Initializes the PartyManager object instance.

Syntax
PartyError Initialize(
PartyString titleId
)

Parameters
titleId PartyString

The app's PlayFab Title ID.


Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via GetErrorMessage().

Remarks
This must be called before any other method, aside from the static methods GetSingleton(),
SetMemoryCallbacks(), GetMemoryCallbacks(), SetThreadAffinityMask(), GetThreadAffinityMask(),
SerializeNetworkDescriptor(), DeserializeNetworkDescriptor(), SetWorkMode(), and GetWorkMode(). Initialize()
cannot be called again without a subsequent Cleanup() call.

Every call to Initialize() should have a corresponding Cleanup() call.

It is recommended for apps using the Xbox One XDK version of the Party library to wait until the platform is
ready for networking operations before calling this method. Please refer to the XDK documentation about
networking and secure device associations best practices for more information.

Apps using the Microsoft Game Core version of the Party library will need to wait for the Game Core
Networking stack to be initialized prior to calling this method. Determining the status of the network stack can
be done using the Game Core XNetworkingGetConnectivityHint API.

Apps using the Microsoft Game Core version of the Party library must listen for app state notifications via the
RegisterAppStateChangeNotification API. When the app is suspended, the app must call
PartyManager::Cleanup(). When the app is resumed, the title must wait for the Game Core networking stack to
ready and then re-initialize the Party library by calling PartyManager::Initialize().

The provided titleId must be the same Title ID used to acquire the PlayFab Entity IDs and Entity Tokens that
will be passed to CreateLocalUser().

Requirements
Header : Party.h

See also
PartyManager
PartyManager::CreateLocalUser
PartyManager::Cleanup
PartyManager::GetSingleton
PartyManager::SetMemoryCallbacks
PartyManager::GetMemoryCallbacks
PartyManager::SetThreadAffinityMask
PartyManager::GetThreadAffinityMask
PartyManager::SerializeNetworkDescriptor
PartyManager::DeserializeNetworkDescriptor
PartyManager::Cleanup
5/24/2022 • 2 minutes to read • Edit Online

Immediately reclaims all resources associated with all Party library objects.

Syntax
PartyError Cleanup(
)

Parameters
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via GetErrorMessage().

Remarks
If local users were participating in a PartyNetwork, they are removed ungracefully (it appears to remote devices
as if network connectivity to this device has been lost), so best practice is to call PartyNetwork::LeaveNetwork()
first on all networks returned from a call to GetNetworks() and wait for the corresponding
PartyLeaveNetworkCompletedStateChange to have the local users exit any existing PartyNetworks gracefully.

This method is not thread-safe and may not be called concurrently with other non-static Party library methods.
After calling this method, all Party library state is invalidated.

Titles using the Microsoft Game Core version of the Party library must listen for app state notifications via the
RegisterAppStateChangeNotification API. When the app is suspended, the title must call
PartyManager::Cleanup(). When the app is resumed, the title must wait for the Game Core networking stack to
be ready and then re-initialize the Party library by calling PartyManager::Initialize().

Every call to Initialize() should have a corresponding Cleanup() call.

Requirements
Header : Party.h

See also
PartyManager
PartyManager::Initialize
PartyNetwork::LeaveNetwork
PartyManager::GetNetworks
PartyManager::StartProcessingStateChanges
5/24/2022 • 2 minutes to read • Edit Online

Retrieves an array of all PartyStateChanges to process since the last such call.

Syntax
PartyError StartProcessingStateChanges(
uint32_t* stateChangeCount,
PartyStateChangeArray* stateChanges
)

Parameters
stateChangeCount uint32_t*
output
The output number of PartyStateChange entries for the title to handle in the stateChanges array.
stateChanges PartyStateChangeArray*
library-allocated output array of size *stateChangeCount
A library-allocated output array of all PartyStateChange entries for the title to handle and then pass to
FinishProcessingStateChanges().
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via GetErrorMessage().

Remarks
This method provides the Party library an opportunity to synchronize state with remote devices or services, and
retrieves a list of all changes currently available for the title since the last call to this method. The title should use
the provided array of 0 or more changes to update its own state or UI, and then call
FinishProcessingStateChanges() with them in a timely manner.

Party library state exposed by the library can change during this call, so you must be thread-safe in your use of
it. For example, invoking StartProcessingStateChanges() on your UI thread at the same time a separate worker
thread is looping through the list of endpoints returned by PartyNetwork::GetEndpoints() may result in crashes
because StartProcessingStateChanges() can alter the memory associated with the endpoint list.
StartProcessingStateChanges() should be called frequently-- at least once per graphics frame. It's designed to
execute and return quickly such that it can be called on your main UI thread with negligible impact. For best
results, you should also minimize the time you spend handling state changes before calling
FinishProcessingStateChanges().

Each state change returned by StartProcessingStateChanges() must be returned to


FinishProcessingStateChanges() exactly once, but may be returned out of order and may be interleaved with
state changes from other calls to StartProcessingStateChanges(). Any resources associated with a specific state
change are guaranteed to stay valid until the state change is returned to FinishProcessingStateChanges().
Requirements
Header : Party.h

See also
PartyManager
PartyStateChange
PartyManager::FinishProcessingStateChanges
PartyManager::FinishProcessingStateChanges
5/24/2022 • 2 minutes to read • Edit Online

Returns an array of PartyStateChanges that were being processed.

Syntax
PartyError FinishProcessingStateChanges(
uint32_t stateChangeCount,
PartyStateChangeArray stateChanges
)

Parameters
stateChangeCount uint32_t
The number of changes, provided in the list specified by stateChanges , previously returned by
StartProcessingStateChanges() that have now been handled by the title.
stateChanges PartyStateChangeArray
input array of size stateChangeCount
The array of changes previously returned by StartProcessingStateChanges() that have now been handled by the
title.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via GetErrorMessage().

Remarks
This method informs the Party library that the state changes reported by a previous call to
StartProcessingStateChanges() have now been handled by the title, so their associated resources can be
reclaimed. You may call FinishProcessingStateChanges() with any number of state changes. Each state change
returned by StartProcessingStateChanges() must be returned to FinishProcessingStateChanges() exactly once,
but may be returned out of order and may be interleaved with state changes from other calls to
StartProcessingStateChanges(). Even if state changes are held across subsequent calls to
StartProcessingStateChanges(), the Party library state returned by all getters will advance and may no longer
reflect the same state that the held state changes refer to.

Any resources associated with a specific state change are guaranteed to stay valid until the state change is
returned to FinishProcessingStateChanges().

For best results, you should minimize the time you spend handling state changes before calling
FinishProcessingStateChanges().

Requirements
Header : Party.h
See also
PartyManager
PartyStateChange
PartyManager::StartProcessingStateChanges
PartyManager::DoWork
5/24/2022 • 2 minutes to read • Edit Online

Synchronously performs the processing task associated with threadId .

Syntax
PartyError DoWork(
PartyThreadId threadId
)

Parameters
threadId PartyThreadId

A high-level categorization of the Party library's internal processing task.


Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via GetErrorMessage().

Remarks
This method will fail and return an error if the work mode of threadId has not previously been set to
PartyWorkMode::Manual via a call to SetWorkMode(). Additionally, on the Windows, Xbox One XDK, and
Microsoft Game Core versions of the library, this method will fail and return an error if the title thread calling
this method does not exist in a COM multithreaded apartment when threadId is PartyThreadId::Networking.

By default, the Party library will internally manage the processing task associated with threadId . However, if the
work mode of threadId is configured as PartyWorkMode::Manual via a call to SetWorkMode(), the title must
periodically call this method to perform the processing task instead.

The processing task associated with threadId dictates the frequency at which this method should be called. The
processing task associated with PartyThreadId::Audio should be performed every 40ms, while the processing
task associated with PartyThreadId::Networking should be performed every 50 to 100ms. Internally, processing
tasks will attempt to handle small variations in timing, but issues will arise if timing strays too far from what is
expected (e.g. audio stutter, network state desynchronization).

For more information on processing task types and timing expectations, see PartyThreadId.

Requirements
Header : Party.h

See also
PartyManager
PartyManager::SetWorkMode
PartyManager::GetWorkMode
PartyManager::GetRegions
5/24/2022 • 2 minutes to read • Edit Online

Gets an array containing the set of regions for which your title is configured, along with round trip latency
information.

Syntax
PartyError GetRegions(
uint32_t* regionCount,
const PartyRegion** regions
)

Parameters
regionCount uint32_t*
output
The output number of regions provided in regions .
regions PartyRegion**
library-allocated output array of size *regionCount

A library-allocated output array containing the set of regions.


Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via GetErrorMessage().

Remarks
The array provided by this method is not populated until the first PartyRegionsChangedStateChange is provided.
Each subsequent PartyRegionsChangedStateChange indicates an update to this set of regions. Background
operations to populate this set begin when Initialize() is called and, if this set hasn't yet been successfully
populated, when CreateNewNetwork() is called.

The array will be sorted in order of increasing latency. Latency for a region is defined as the end-to-end time it
takes to send a UDP datagram to the PlayFab Quality of Service beacon for that region and receive a response.
The library will measure latency for each region several times in order to calculate high fidelity results.

A latency equivalent to UINT32_MAX indicates that the region is supported but latency information could not be
determined, either due to failures internal to the library or a ping timeout was reached without receiving a
response from the beacon. This can be used for diagnostic purposes (a UINT32_MAX latency to every region
likely indicates a local configuration problem) or used to filter out regions that are unlikely to be viable during
region selection.

The returned names in the PartyRegion structures are not localized to the current user's language, and showing
the strings directly in UI is not recommended outside of troubleshooting.
You shouldn't assume the set of regions returned will remain the same over the life of your title. The PlayFab
Party library will automatically take advantage of additions and changes to available regions over time to
continually improve the experience for end users.

After internally retrieving the set of regions, the worst-case time for failing latency measurements to every
region would be approximately 500 milliseconds multiplied by the number of regions, but measurements are
actually performed in parallel to reduce the overall duration. Successful latency measurement time varies by
network environment. Currently most devices worldwide successfully complete the entire measurement process
in 2.2 seconds or less, and 95% of devices successfully complete in less than 6 seconds. This may increase
slightly over time as additional regions are introduced.

Requirements
Header : Party.h

See also
PartyManager
PartyRegionsChangedStateChange
PartyManager::CreateNewNetwork
PartyManager::CreateNewNetwork
5/24/2022 • 6 minutes to read • Edit Online

Queues an asynchronous attempt to create a new network.

Syntax
PartyError CreateNewNetwork(
const PartyLocalUser* localUser,
const PartyNetworkConfiguration* networkConfiguration,
uint32_t regionCount,
const PartyRegion* regions,
const PartyInvitationConfiguration* initialInvitationConfiguration,
void* asyncIdentifier,
PartyNetworkDescriptor* networkDescriptor,
char* appliedInitialInvitationIdentifier
)

Parameters
localUser PartyLocalUser*
The local user to which the network creation and relay allocation is attributed.
networkConfiguration PartyNetworkConfiguration*
Network configuration properties such as max user count and max device count. These properties last for the
lifetime of the network and cannot be changed.
regionCount uint32_t
The number of regions provided in the array of preferred regions specified via regions . If this is zero, the
library will use all regions in which the title is configured, ordered by lowest round trip latency from this device.
regions PartyRegion*
The array of preferred regions in which the network should be created. The network will be created in the first
available region.
initialInvitationConfiguration PartyInvitationConfiguration*
optional
An optionally specified configuration for the initial invitation.

If this value is null, then default configuration values will be used. By default, PlayFab Party will generate a
unique invitation identifier for the title, the revocability will be PartyInvitationRevocability::Anyone, and the
PlayFab Entity ID list will be empty, allowing any user to join using the invitation.

If a configuration is provided, the title may optionally specify the identifier on the configuration. If the identifier
is nullptr or an empty string, the PlayFab Party library will generate an identifier for the title. It is guaranteed that
this generated identifier will be different from all identifiers that the PlayFab Party library will generate for all
future invitations on this network across all devices. Titles may specify their own identifier by providing a non-
null, non-empty value in the configuration. If the title specifies the identifier, it is the title's responsibility to
ensure that this identifier does not collide with the identifiers of future invitations created on this network via
PartyNetwork::CreateInvitation() on any device.

If a configuration is provided, its revocability must be PartyInvitationRevocability::Anyone.

If a configuration is provided and the list of PlayFab Entity IDs is empty, all users will be allowed to join using the
new invitation.
asyncIdentifier void*
optional
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
networkDescriptor PartyNetworkDescriptor*
optional output
The optional, output network descriptor that can be used to immediately queue a connection of the local device
to the newly created network via ConnectToNetwork().
appliedInitialInvitationIdentifier char*
optional output string buffer of size c_maxInvitationIdentifierStringLength+1

The optional, output buffer to which the initial invitation's identifier is written. If initialInvitationConfiguration
has been provided with a non-null, non-empty identifier, then this buffer will be filled with the same identifier. If
an initial configuration was not provided or the provided configuration had an empty or null identifier, the
PlayFab Party library will generate one and return it to the title in this buffer.
Return value
PartyError
c_partyErrorSuccess if the asynchronous operation to create a new network began, or an error code otherwise.
If this method fails, no related state changes will be generated. The human-readable form of the error code can
be retrieved via GetErrorMessage().

Remarks
A PartyNetwork is a set of devices, such as Xbox One consoles and PCs, that are connected via a client-server
topology to a transparent cloud relay server. Each device in the network contains a collection of endpoints
associated with the network; directed messages can be sent from an endpoint on the local device to any set of
endpoints, or broadcast to all endpoints. This method queues an attempt to allocate a relay, thus creating a new
network, on behalf of the user represented by localUser but does not connect the local device to the network.

If no devices connect to the network within ten minutes of the relay's creation, it will shut down. The network
will stay active indefinitely while at least one device is connected, migrating to a new relay if required. If no
devices are connected to the network, the relay will become inactive and shut down after one minute of
inactivity.

The local device can queue an attempt to connect to the new network by immediately passing
networkDescriptor to ConnectToNetwork(). Using this descriptor with SerializeNetworkDescriptor() will result in
failure because the descriptor does not contain enough information for a remote device to connect to the
network. The network descriptor changes and becomes serializable when the
PartyCreateNewNetworkCompletedStateChange is provided and indicates success. The updated network
descriptor is provided as a field in the PartyCreateNewNetworkCompletedStateChange. Once connected to the
network, the descriptor can be retrieved using PartyNetwork::GetNetworkDescriptor().
The network is created in the first available region using the order specified in regions . If none of the specified
regions are available, the network will not be created. Specifying 0 for regionCount defaults to using all regions
in which the title is configured, ordered by lowest latency to this device.

Note that the default region selection only includes latency measurements from this device and not from any
other devices. Titles that have a set of participants for the session known up front should implement
functionality to gather measurements from all devices prior to creating the network and construct a new
regions array ordered by lowest aggregate latency for the whole group.

For titles that support join-in-progress, the region with the best overall latency for the group of connected
participants may change as devices join and leave. Titles should take advantage of Party's support for being
connected to multiple networks simultaneously to migrate devices seamlessly to a network created in a region
with better aggregate latency for the group. The title can gather region latency measurements via messages
over the original Party network or information uploaded to an external roster service, create a new Party
network in a region with lower aggregate latency, and instruct all devices to connect to the more favorable
network and disconnect from the original one.

The initial invitation for the newly created network will not be owned by any user. Therefore calling
PartyInvitation::GetCreatorEntityId() will return nullptr for the initial invitation. As well, the initial invitation for
the newly created network will persist for the lifetime of the network until specifically revoked via
PartyNetwork::RevokeInvitation(). New invitations can be created for the network via
PartyNetwork::CreateInvitation() by local users that are authenticated into the network, and those invitations will
persist until their creating local users are removed from the network. Users join the network via
PartyNetwork::AuthenticateLocalUser() by providing the identifier of an invitation that was successfully created,
has not been revoked, and allows them to join.
Retrying on failure
When CreateNewNetwork() fails asynchronously, a PartyCreateNewNetworkCompletedStateChange is provided
by StartProcessingStateChanges indicating the result. The operation may be retried after a delay, depending on
the PartyStateChangeResult provided.

RESULT RET RY B EH AVIO R

InternetConnectivityError Retry with a small delay of no less than 10 seconds. For your
app, it may be more appropriate to display the error to the
user immediately, rather than retrying automatically.

PartyServiceError Retry with an exponential backoff. Start with a minimum


delay of no less than 10 seconds, doubling the delay with
each retry.

NoServersAvailable Retry with an exponential backoff. Start with a minimum


delay of no less than 30 seconds, doubling the delay with
each retry. For your app, it may be more appropriate to
display the error to the user immediately, rather than
retrying automatically.

UserNotAuthorized This result can mean that the user's entity token was invalid,
expired, or that the user was not authorized for other
reasons. Retry no more than one time, and only after getting
a new entity token for the user and calling
PartyLocalUser::UpdateEntityToken().
RESULT RET RY B EH AVIO R

UserCreateNetworkThrottled Do not retry automatically. Instead, display a message to the


user and wait for the user to initiate another attempt.

FailedToBindToLocalUdpSocket This result means that the library couldn't bind to the local
UDP socket specified in the
PartyOption::LocalUdpSocketBindAddress option. The title
must clean up its instance of the library, update the
PartyOption::LocalUdpSocketBindAddress option to a valid,
available bind address, and re-initialize the library.

Requirements
Header : Party.h

See also
PartyManager
PartyCreateNewNetworkCompletedStateChange
PartyManager::ConnectToNetwork
PartyNetwork::AuthenticateLocalUser
PartyNetwork::LeaveNetwork
PartyNetwork::RevokeInvitation
PartyNetwork::CreateInvitation
PartyInvitation
PartyInvitationConfiguration
PartyManager::ConnectToNetwork
5/24/2022 • 2 minutes to read • Edit Online

Queues an asynchronous attempt to connect to a network.

Syntax
PartyError ConnectToNetwork(
const PartyNetworkDescriptor* networkDescriptor,
void* asyncIdentifier,
PartyNetwork** network
)

Parameters
networkDescriptor PartyNetworkDescriptor*
The descriptor associated with the network to which a connection will be established.
asyncIdentifier void*
optional
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
network PartyNetwork**
optional, library-allocated output
The optional, output network object.
Return value
PartyError
c_partyErrorSuccess if the asynchronous operation to connect to a new network began, or an error code
otherwise. If this method fails, no related state changes will be generated. The human-readable form of the error
code can be retrieved via GetErrorMessage().

Remarks
This method queues an asynchronous attempt to connect to the network associated with networkDescriptor by
negotiating and establishing a secure DTLS connection from the local device to the transparent cloud relay
server. A PartyConnectToNetworkCompletedStateChange will be provided upon completion of the
asynchronous operation, indicating success or failure. On success, the local device will have established a
connection to the transparent cloud relay server. On failure, a PartyNetworkDestroyedStateChange will be
generated. No other devices will become visible, and the local device will not be visible to any remote devices,
until at least one local user is successfully authenticated via PartyNetwork::AuthenticateLocalUser().

After the device successfully connects to the network, it must authenticate into the network via
PartyNetwork::AuthenticateLocalUser(). If the device is connected to the network but unauthenticated for more
than one minute, the device will be disconnected and a PartyNetworkDestroyedStateChange will be generated.
This will occur regardless of whether the device never authenticated or lost authentication after calling
PartyNetwork::RemoveLocalUser().
This method optionally provides network as output that can immediately be used to perform asynchronous
network operations, such as PartyNetwork::CreateInvitation() and PartyNetwork::CreateEndpoint(). These
asynchronous operations will be internally queued until the connection completes, at which point they will be
processed. This network will also be provided on the resulting PartyConnectToNetworkCompletedStateChange
where it will be fully connected and associated with the provided asyncIdentifier .

This operation will asynchronously fail with PartyConnectToNetworkCompletedStateChange::result set to


PartyStateChangeResult::NetworkLimitReached if the limit of connected devices for the network has been
reached as specified in the network's configuration when it was created via CreateNewNetwork().

On successful return, this method invalidates the memory for any array previously returned by GetNetworks(),
as it synchronously adds the new network to the array. StartProcessingStateChanges() also invalidates the
memory for the array. The returned network object will be valid until a PartyNetworkDestroyedStateChange has
been generated and all state changes referencing the object have been returned to
FinishProcessingStateChanges().
Retrying on failure
When ConnectToNetwork() fails asynchronously, a PartyConnectToNetworkCompletedStateChange is provided
by StartProcessingStateChanges() indicating the result. The operation may be retried after a delay, depending on
the PartyStateChangeResult provided.

RESULT RET RY B EH AVIO R

InternetConnectivityError Retry with a small delay of no less than 10 seconds. For your
app, it may be more appropriate to display the error to the
user immediately, rather than retrying automatically.

NetworkLimitReached Do not retry automatically. Instead, display a message to the


user and wait for the user to initiate another attempt.

NetworkNoLongerExists Do not retry.

VersionMismatch Do not retry.

FailedToBindToLocalUdpSocket This result means that the library couldn't bind to the local
UDP socket specified in the
PartyOption::LocalUdpSocketBindAddress option. The title
must clean up its instance of the library, update the
PartyOption::LocalUdpSocketBindAddress option to a valid,
available bind address, and re-initialize the library.

Requirements
Header : Party.h

See also
PartyManager
PartyConnectToNetworkCompletedStateChange
PartyNetworkDestroyedStateChange
PartyNetworkConfiguration
PartyManager::CreateNewNetwork
PartyManager::GetNetworks
PartyNetwork::AuthenticateLocalUser
PartyNetwork::RemoveLocalUser
PartyNetwork::CreateInvitation
PartyNetwork::RevokeInvitation
PartyNetwork::CreateEndpoint
PartyNetwork::LeaveNetwork
PartyManager::GetLocalDevice
5/24/2022 • 2 minutes to read • Edit Online

Gets the local device.

Syntax
PartyError GetLocalDevice(
PartyLocalDevice** localDevice
)

Parameters
localDevice PartyLocalDevice**
library-allocated output
The output local device.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via GetErrorMessage().

Remarks
The local device represents the physical device on which the title is executing, such as an Xbox One or PC. Once
the library is initialized, this method will always succeed in returning a local device. The local device will also
appear in the device list of any network to which the local device has connected via ConnectToNetwork().

Requirements
Header : Party.h

See also
PartyManager
PartyManager::CreateLocalUser
5/24/2022 • 2 minutes to read • Edit Online

Creates a local user object that is used to represent a local user when performing networking and chat
operations.

Syntax
PartyError CreateLocalUser(
PartyString entityId,
PartyString titlePlayerEntityToken,
PartyLocalUser** localUser
)

Parameters
entityId PartyString

The PlayFab Entity ID to associate with the local user.


titlePlayerEntityToken PartyString
The PlayFab Entity Token to associate with the local user.
localUser PartyLocalUser**
library-allocated output
The output local user object.
Return value
PartyError
c_partyErrorSuccess if creating the local user succeeded or an error code otherwise. The human-readable form
of the error code can be retrieved via GetErrorMessage().

Remarks
This method takes a PlayFab Entity ID as entityId and a PlayFab Entity Token as titlePlayerEntityToken . No
synchronous validation is performed on these values except that the length of entityId is less than or equal to
c_maxEntityIdStringLength . When the library performs operations that require user authentication or
authorization, such as creating a network, authenticating into a network, or performing speech-to-text
transcription, the Party service will validate that the token is valid, is not expired, is associated with the Entity ID
provided, and is authorized to perform the operation. If these conditions aren't met, the operation will fail.

A PlayFab Entity ID and Entity Token can be obtained from the output of a PlayFab login operation and then
provided as input to this method. The PlayFab Entity ID must be of type title_player_account , which, for most
developers, represents the "player" in the most traditional way.

The provided entityId and titlePlayerEntityToken must have been acquired using the same Title ID that was
passed to Initialize().

The Party library makes a copy of the supplied PlayFab Entity Token for use in subsequent operations that
require authentication or authorization of the local user, such as CreateNewNetwork() or
PartyNetwork::AuthenticateLocalUser(). If the token provided to this call is expired or otherwise invalid,
operations that require a valid token will fail. A new, valid token can be provided to the Party library via a call to
PartyLocalUser::UpdateEntityToken().

The caller is responsible for monitoring the expiration of the entity token provided to this method and
PartyLocalUser::UpdateEntityToken(). When the token is nearing or past the expiration time a new token should
be obtained by performing a PlayFab login operation and provided to the Party library by calling
PartyLocalUser::UpdateEntityToken(). It is recommended to acquire a new token when the previously supplied
token is halfway through its validity period. On platforms that may enter a low power state or otherwise cause
the application to pause execution for a long time, preventing the token from being refreshed before it expires,
the token should be checked for expiration once execution resumes.

Only c_maxLocalUsersPerDeviceCount PartyLocalUser objects may exist simultaneously at any given time. This
method will synchronously fail if creating another local user would exceed that limit.

On successful return, this method invalidates the memory for any array previously returned by GetLocalUsers(),
as it synchronously adds the new user to the array. StartProcessingStateChanges() also invalidates the memory
for the array. The returned localUser object will be valid until a PartyDestroyLocalUserCompletedStateChange
has been generated and all state changes referencing the object have been returned to
FinishProcessingStateChanges().

Requirements
Header : Party.h

See also
PartyManager
PartyDestroyLocalUserCompletedStateChange
PartyManager::Initialize
PartyManager::GetLocalUsers
PartyManager::DestroyLocalUser
PartyManager::CreateNewNetwork
PartyNetwork::AuthenticateLocalUser
PartyNetwork::RemoveLocalUser
PartyNetwork::CreateInvitation
PartyNetwork::RevokeInvitation
PartyNetwork::CreateEndpoint
PartyLocalUser::UpdateEntityToken
PartyLocalDevice::CreateChatControl
PartyManager::DestroyLocalUser
5/24/2022 • 2 minutes to read • Edit Online

Starts an asynchronous operation to destroy a local user.

Syntax
PartyError DestroyLocalUser(
const PartyLocalUser* localUser,
void* asyncIdentifier
)

Parameters
localUser PartyLocalUser*
The local user to destroy.
asyncIdentifier void*
optional
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
Return value
PartyError
c_partyErrorSuccess if the operation to destroy the local user started or an error code otherwise. If this method
fails, no related state changes will be generated. The human-readable form of the error code can be retrieved via
GetErrorMessage().

Remarks
This method queues an asynchronous operation to destroy a local user. A
PartyDestroyLocalUserCompletedStateChange will be provided upon completion of the operation, indicating
success or failure. Before successful completion of the operation, the local user will be removed from all
networks it has authenticated into (each indicated by a PartyLocalUserRemovedStateChange) and any local chat
control associated with the user will be destroyed (indicated by a PartyChatControlDestroyedStateChange).
Memory for the local user will remain valid until all state changes referencing the local user have been returned
to PartyManager::FinishProcessingStateChanges().

Requirements
Header : Party.h

See also
PartyManager
PartyDestroyLocalUserCompletedStateChange
PartyChatControlDestroyedStateChange
PartyLocalUserRemovedStateChange
PartyManager::GetLocalUsers
PartyManager::GetLocalUsers
5/24/2022 • 2 minutes to read • Edit Online

Gets an array containing all local users created by CreateLocalUser().

Syntax
PartyError GetLocalUsers(
uint32_t* userCount,
PartyLocalUserArray* localUsers
)

Parameters
userCount uint32_t*
output
The output number of local users provided in localUsers .
localUsers PartyLocalUserArray*
library-allocated output array of size *userCount

A library-allocated output array containing the local users.


Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via GetErrorMessage().

Remarks
Once a PartyDestroyLocalUserCompletedStateChange has been provided by
PartyManager::StartProcessingStateChanges(), the local user will no longer be present in the array returned by
this method.

The memory for the returned array is invalidated whenever the title calls
PartyManager::StartProcessingStateChanges() or CreateLocalUser() returns success.

Requirements
Header : Party.h

See also
PartyManager
PartyManager::CreateLocalUser
PartyManager::DestroyLocalUser
PartyDestroyLocalUserCompletedStateChange
PartyManager::GetNetworks
5/24/2022 • 2 minutes to read • Edit Online

Gets an array of all networks to which the local device is connected or connecting.

Syntax
PartyError GetNetworks(
uint32_t* networkCount,
PartyNetworkArray* networks
)

Parameters
networkCount uint32_t*
output
The output number of networks to which the local device is connected or connecting provided in networks .
networks PartyNetworkArray*
library-allocated output array of size *networkCount

A library-allocated output array containing the networks to which the local device is connected or connecting.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via GetErrorMessage().

Remarks
Once a PartyNetworkDestroyedStateChange has been provided by
PartyManager::StartProcessingStateChanges(), the network will no longer be present in the array returned by
this method.

The memory for the returned array is invalidated whenever the title calls
PartyManager::StartProcessingStateChanges() or ConnectToNetwork() returns success.

Requirements
Header : Party.h

See also
PartyManager
PartyManager::ConnectToNetwork
PartyNetwork::LeaveNetwork
PartyNetworkDestroyedStateChange
PartyManager::GetChatControls
5/24/2022 • 2 minutes to read • Edit Online

Gets an array that contains a combined list of all chat controls on the local device and all remote devices.

Syntax
PartyError GetChatControls(
uint32_t* chatControlCount,
PartyChatControlArray* chatControls
)

Parameters
chatControlCount uint32_t*
output
The output number of chat controls provided in chatControls .
chatControls PartyChatControlArray*
library-allocated output array of size *chatControlCount
A library-allocated output array containing the list of all chat controls.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via GetErrorMessage().

Remarks
Once a PartyChatControlDestroyedStateChange has been provided by
PartyManager::StartProcessingStateChanges(), the chat control will no longer be present in the array returned
by this method.

The memory for the returned array is invalidated whenever the title calls
PartyManager::StartProcessingStateChanges() or PartyLocalDevice::CreateChatControl() returns success.

Requirements
Header : Party.h

See also
PartyManager
PartyLocalDevice::CreateChatControl
PartyLocalDevice::DestroyChatControl
PartyChatControlDestroyedStateChange
PartyNetwork
5/24/2022 • 2 minutes to read • Edit Online

Represents a network.

Syntax
class PartyNetwork

Public Methods
NAME DESC RIP T IO N

AuthenticateLocalUser Queues an asynchronous operation to authenticate the


specified local user into the network.

RemoveLocalUser Queues an asynchronous operation to remove a local user


from the network.

CreateInvitation Queues an asynchronous attempt to create an invitation for


the network.

RevokeInvitation Queues an asynchronous attempt to revoke an invitation


from the network.

GetInvitations Gets an array containing all invitations exposed to the local


device.

CreateEndpoint Queues an asynchronous attempt to create a local endpoint.

DestroyEndpoint Queues an asynchronous operation to destroy a local


endpoint.

LeaveNetwork Queues an asynchronous operation to leave the network


gracefully.

GetEndpoints Gets the endpoints in this network.

FindEndpointByUniqueIdentifier Finds the endpoint with the corresponding network-unique


identifier in this network, if it exists.

GetDevices Gets the devices in this network.

GetLocalUsers Gets an array containing the local users that are


authenticated or authenticating into the network.

GetNetworkDescriptor Gets the network descriptor for this network.


NAME DESC RIP T IO N

GetNetworkConfiguration Gets the network configuration which was set when creating
the network.

ConnectChatControl Connects the local chat control to the network.

DisconnectChatControl Disconnects the local chat control from the network.

GetChatControls Gets the chat controls connected to this network.

GetNetworkStatistics Gets one or more statistic counter values for the network.

GetCustomContext Retrieves the app's private, custom pointer-sized context


value previously associated with this network object.

SetCustomContext Configures an optional, custom pointer-sized context value


with this network object.

GetDeviceConnectionType Retrieves the type of connection used by the local device for
transmitting messages or chat data to the specified target
device in this network.

Requirements
Header : Party.h

See also
Party members
PartyNetwork::AuthenticateLocalUser
5/24/2022 • 4 minutes to read • Edit Online

Queues an asynchronous operation to authenticate the specified local user into the network.

Syntax
PartyError AuthenticateLocalUser(
const PartyLocalUser* localUser,
PartyString invitationIdentifier,
void* asyncIdentifier
)

Parameters
localUser PartyLocalUser*
The local user to authenticate into the network.
invitationIdentifier PartyString
The identifier of the invitation that allows the localUser to authenticate into the network.
asyncIdentifier void*
optional
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
Return value
PartyError
c_partyErrorSuccess if the asynchronous operation to authenticate the local user began, or an error code
otherwise. If this method fails, no related state changes will be generated. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
While any device with the appropriate network descriptor can establish a connection to the network, no useful
actions can be performed, and no useful information can be gleaned, without first authenticating a local user on
the device into the network. As such, authentication is an important security measure to ensure the integrity of
the network and the privacy of the devices and users participating in the network. To authenticate a user is to
have the transparent cloud relay server validate the user's identity and that the user is allowed to join the
network.

Upon successful completion of the asynchronous operation started by this call, a user is considered
authenticated into the network. Completion is indicated by the
PartyAuthenticateLocalUserCompletedStateChange. Successful authentication requires that the local user's
PlayFab Entity Token is valid and is associated with the local user's PlayFab Entity ID. Successful authentication
also requires that the provided invitation allows the provided local user to join the network. Authentication will
fail if authenticating the provided user would violate one of the limits in the network's configuration. These
requirements are enforced by the transparent cloud relay server. If the asynchronous operation fails, the
PartyAuthenticateLocalUserCompletedStateChange will provide a diagnostic result and error detail, and a
PartyLocalUserRemovedStateChange will be generated. Because being connected to a network with no
authenticated users is not a useful state outside of transition periods, the Party library will automatically
disconnect a device that does not have an authenticated user for an extended period.

Users need an invitationIdentifier to call this method and authenticate into the network. Most commonly this
means that another device will have to share the identifier of the initial invitation generated via
PartyManager::CreateNewNetwork() or share the identifier of an invitation it has generated via
CreateInvitation().

User authentication also determines device authentication. A device is considered authenticated into the
network if at least one local user is authenticated into the network. If a device is authenticated into the network,
it will be visible to all other authenticated devices. If a device is connected to the network but not authenticated,
no remote devices, endpoints, or chat controls, will be visible. Similarly, the device will not be visible to any other
devices connected to the network.

Once this method is called, all other methods that queue asynchronous operations but require the local user or
local device to be authenticated into the network can be called. Such operations will be queued until completion
of the authentication operation. Once the authentication operation completes, the queued operations will be
processed. If the authentication operation failed, the queued operations will also fail and their respective
completion state changes will indicate such.

If the local device enters a state in which there are no authenticated users and no authentication operations in
progress, then all endpoints, including those that are not fully created, will be destroyed automatically. This will
be signaled by PartyEndpointDestroyedStateChanges.

On successful return, this method invalidates the memory for any array previously returned by
PartyNetwork::GetLocalUsers(), as it synchronously adds the new user to the array.
PartyManager::StartProcessingStateChanges() also invalidates the memory for the array.

This method will fail if the specified localUser is in the process of authenticating into the network, is already
authenticated into the network, is authenticated but in the process of being removed due to a previous call to
PartyNetwork::RemoveLocalUser(), or if the device overall is in the process of becoming unauthenticated due to
its last authenticated user being removed from the network.
Retrying on failure
If the PartyAuthenticateLocalUserCompletedStateChange associated with the completion of this call indicates a
failure, the operation may be retried after a delay. The proper retry behavior depends on the
PartyStateChangeResult provided in the state change.

RESULT RET RY B EH AVIO R

InternetConnectivityError Retry with a small delay of no less than 10 seconds. For your
app, it may be more appropriate to display the error to the
user immediately, rather than retrying automatically.

PartyServiceError Retry with an exponential backoff. Start with a minimum


delay of no less than 10 seconds, doubling the delay with
each retry.
RESULT RET RY B EH AVIO R

UserNotAuthorized This result can mean that the user's entity token was invalid,
expired, or that the user was not authorized for other
reasons. It could also mean that specified invitation is no
longer valid, or the invitation does not contain this user.
Retry no more than one time, and only after getting a new
entity token for the user and calling
PartyLocalUser::UpdateEntityToken().

FailedToBindToLocalUdpSocket This result means that the library couldn't bind to the local
UDP socket specified in the
PartyOption::LocalUdpSocketBindAddress option. The title
must clean up its instance of the library, update the
PartyOption::LocalUdpSocketBindAddress option to a valid,
available bind address, and re-initialize the library.

Requirements
Header : Party.h

See also
PartyNetwork
PartyAuthenticateLocalUserCompletedStateChange
PartyEndpointDestroyedStateChange
PartyLocalUserRemovedStateChange
PartyNetworkConfiguration
PartyManager::CreateLocalUser
PartyNetwork::RemoveLocalUser
PartyNetwork::GetLocalUsers
PartyManager::CreateNewNetwork
PartyNetwork::CreateInvitation
PartyNetwork::RemoveLocalUser
5/24/2022 • 2 minutes to read • Edit Online

Queues an asynchronous operation to remove a local user from the network.

Syntax
PartyError RemoveLocalUser(
const PartyLocalUser* localUser,
void* asyncIdentifier
)

Parameters
localUser PartyLocalUser*
The local user to remove from the network.
asyncIdentifier void*
optional
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
Return value
PartyError
c_partyErrorSuccess if the asynchronous operation to remove the local user began, or an error code otherwise.
If this method fails, no related state changes will be generated. The human-readable form of the error code can
be retrieved via PartyManager::GetErrorMessage().

Remarks
Upon completion of the asynchronous operation, a user is no longer considered authenticated into the network.
Completion is indicated by a PartyRemoveLocalUserCompletedStateChange. The asynchronous operation will
always succeed, and a PartyLocalUserRemovedStateChange will always be provided before the
PartyRemoveLocalUserCompletedStateChange. Before successful completion of the operation, all endpoints
associated with that user will be destroyed (each indicated by a PartyEndpointDestroyedStateChange) and all
chat controls associated with that user will be disconnected from the network (each indicated by a
PartyChatControlLeftNetworkStateChange).

When all local users are removed from the network, the device is no longer considered authenticated. All
endpoints are destroyed and all remote devices will appear to leave the network, because they are no longer
visible to the local device. Similarly, all remote devices will see the local device as having left the network. The
device will not immediately be disconnected and can again be authenticated by a new call to
AuthenticateLocalUser(). However, because being connected to a network with no authenticated users is not a
useful state outside of transition periods, the Party library will automatically disconnect a device that is
unauthenticated for more than one minute.

This method will fail if the specified localUser is already in the process of being removed from the network due
to a previous call to this method.
Requirements
Header : Party.h

See also
PartyNetwork
PartyRemoveLocalUserCompletedStateChange
PartyEndpointDestroyedStateChange
PartyChatControlLeftNetworkStateChange
PartyNetwork::AuthenticateLocalUser
PartyNetwork::GetLocalUsers
PartyNetwork::CreateInvitation
5/24/2022 • 3 minutes to read • Edit Online

Queues an asynchronous attempt to create an invitation for the network.

Syntax
PartyError CreateInvitation(
const PartyLocalUser* localUser,
const PartyInvitationConfiguration* invitationConfiguration,
void* asyncIdentifier,
PartyInvitation** invitation
)

Parameters
localUser PartyLocalUser*
The local user that owns the invitation in the network. If this local user leaves the network for any reason the
invitation will be automatically revoked.
invitationConfiguration PartyInvitationConfiguration*
optional
An optionally specified configuration for the newly created invitation.

If this value is null, the default configuration values will be used. By default, PlayFab Party will generate a unique
invitation identifier for the title, the revocability will be PartyInvitationRevocability::Creator, and the PlayFab
Entity ID list will be empty, allowing any user to join using the invitation.

If a configuration is provided, the title may optionally specify the identifier on the configuration. If the identifier
is nullptr or an empty string, the PlayFab Party library will generate an identifier for the title. It is guaranteed that
this generated identifier will be different from all identifiers that the PlayFab Party library has already generated
for invitations on this network across all devices. Titles may specify their own identifier by providing a non-null,
non-empty value in the configuration. If the title specifies the identifier, it is the title's responsibility to ensure
that this identifier does not collide with the identifiers of other invitations created on this network via
PartyManager::CreateNewNetwork() or CreateInvitation() on any device. If the title attempts to create an
invitation with an identifier that would collide with a pre-existing invitation, then the operation will fail
asynchronously and the title will receive a PartyInvitationDestroyedStateChange followed by a
PartyCreateInvitationCompletedStateChange with a failure result.

If a configuration is provided, its revocability must be PartyInvitationRevocability::Creator.

If a configuration is provided and the list of PlayFab Entity IDs is empty, all users will be allowed to join using the
new invitation.
asyncIdentifier void*
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
invitation PartyInvitation**
optional, library-allocated output
The optional, output invitation that may immediately be used to queue user authentications on a network via
AuthenticateLocalUser().
Return value
PartyError
c_partyErrorSuccess if the asynchronous operation to create an invitation began, or an error code otherwise. If
this method fails, no related state changes will be generated. The human-readable form of the error code can be
retrieved via PartyManager::GetErrorMessage().

Remarks
To join a network, a user must provide an invitation to AuthenticateLocalUser().

This method queues an asynchronous attempt to create an invitation for the network. A
PartyCreateInvitationCompletedStateChange will be provided upon completion of the asynchronous operation,
indicating success or failure. On success, a PartyInvitationCreatedStateChange will have been generated
beforehand to indicate that the transparent cloud relay server is ready to accept authentications using the
invitation's identifier. On failure, a PartyInvitationDestroyedStateChange will have been generated beforehand to
indicate that the invitation object is no longer valid and will no longer be queryable via GetInvitations().

The lifetime of the invitation is tied to the owning local user's membership in the network, therefore localUser
must be authenticated or in the process of authenticating. If localUser leaves the network for any reason the
invitation will be automatically revoked and subsequent attempts to use that invitation's identifier to join the
network will fail until a new invitation is created using that identifier.

Invitations created with this method will only be queryable via GetInvitations() on the local device where the
invitation was created.

On successful return, this method invalidates the memory for any array previously returned by GetInvitations(),
as it synchronously adds the new invitation to the array. PartyManager::StartProcessingStateChanges() also
invalidates the memory for the array. The returned invitation object will be valid until a
PartyInvitationDestroyedStateChange has been generated and all state changes referencing the object have
been returned to PartyManager::FinishProcessingStateChanges().

Requirements
Header : Party.h

See also
PartyNetwork
PartyInvitationRevocability
PartyNetwork::AuthenticateLocalUser
PartyInvitationCreatedStateChange
PartyCreateInvitationCompletedStateChange
PartyInvitationDestroyedStateChange
PartyManager::CreateNewNetwork
PartyNetwork::RevokeInvitation
5/24/2022 • 2 minutes to read • Edit Online

Queues an asynchronous attempt to revoke an invitation from the network.

Syntax
PartyError RevokeInvitation(
const PartyLocalUser* localUser,
PartyInvitation* invitation,
void* asyncIdentifier
)

Parameters
localUser PartyLocalUser*
The local user attempting to revoke the invitation.
invitation PartyInvitation*
The invitation to revoke.
asyncIdentifier void*
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
Return value
PartyError
c_partyErrorSuccess if the asynchronous operation to revoke the invitation began, or an error code otherwise. If
this method fails, no related state changes will be generated. The human-readable form of the error code can be
retrieved via PartyManager::GetErrorMessage().

Remarks
Titles may revoke an invitation to prevent further users from authenticating into a network using the invitation's
identifier.

This method queues an asynchronous attempt to revoke an invitation from the network. A
PartyRevokeInvitationCompletedStateChange will be provided upon completion of the asynchronous operation,
indicating success or failure. On success, a PartyInvitationDestroyedStateChange will have been generated
beforehand with PartyDestroyedReason::Requested, to indicate that the network will no longer accept
authentications using the invitation's identifier until a new invitation is created with that same identifier. It also
indicates that the invitation will no longer be queryable via GetInvitations().

This operation will only succeed if the invitation was created with its revocability specified such that the
localUser on the local device may revoke the invitation. This might not be the case if the revocability is set to
PartyInvitationRevocability::Creator and the localUser is authenticated on a different device than the creator or
if the localUser refers to a different user than the creator.
Requirements
Header : Party.h

See also
PartyNetwork
PartyRevokeInvitationCompletedStateChange
PartyInvitationDestroyedStateChange
PartyNetwork::GetInvitations
5/24/2022 • 2 minutes to read • Edit Online

Gets an array containing all invitations exposed to the local device.

Syntax
PartyError GetInvitations(
uint32_t* invitationCount,
PartyInvitationArray* invitations
)

Parameters
invitationCount uint32_t*
output
An output value indicating the number of invitations provided in invitations .
invitations PartyInvitationArray*
library-allocated output array of size *invitationCount

A library-allocated output array containing the invitations that have been created for the network.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
The array is backed by the library's internal memory. The array is only valid until the next call to either
CreateInvitation() or PartyManager::StartProcessingStateChanges().

A new invitation is exposed to the local device whenever the local device calls CreateInvitation() or a
PartyInvitationCreatedStateChange is provided via PartyManager::StartProcessingStateChanges().

Invitations created via CreateInvitation() will only be exposed to the local device. The initial invitation will be
exposed to all devices in the network via a PartyInvitationCreatedStateChange.

Once a PartyInvitationDestroyedStateChange has been provided by


PartyManager::StartProcessingStateChanges(), the invitation will no longer be present in the array returned by
this method.

Requirements
Header : Party.h

See also
PartyNetwork
PartyManager::CreateNewNetwork
PartyNetwork::CreateInvitation
PartyNetwork::RevokeInvitation
PartyInvitationCreatedStateChange
PartyInvitationDestroyedStateChange
PartyNetwork::CreateEndpoint
5/24/2022 • 3 minutes to read • Edit Online

Queues an asynchronous attempt to create a local endpoint.

Syntax
PartyError CreateEndpoint(
const PartyLocalUser* localUser,
uint32_t propertyCount,
const PartyString* keys,
const PartyDataBuffer* values,
void* asyncIdentifier,
PartyLocalEndpoint** localEndpoint
)

Parameters
localUser PartyLocalUser*
optional
An optional local user to associate as the owner of this endpoint. When this endpoint becomes visible on remote
devices, the user's identifier will be tied to this endpoint. The endpoint will be destroyed if the user becomes
unauthenticated because they were voluntarily removed via RemoveLocalUser() or kicked via
PartyNetwork::KickUser().
propertyCount uint32_t
The number of properties in the input keys and values arrays. Property bags are currently unimplemented.
This parameter must be zero.
keys PartyString*
optional input array of size propertyCount

The propertyCount entry array of property bag keys. The nth key in this array maps to the nth value in the
values array. Property bags are currently unimplemented. This parameter must be nullptr.
values PartyDataBuffer*
optional input array of size propertyCount

The propertyCount entry array of property bag values. The nth value in this array is mapped by the nth key in
the keys array. Property bags are currently unimplemented. This parameter must be nullptr.
asyncIdentifier void*
optional
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
localEndpoint PartyLocalEndpoint**
optional, library-allocated output
The optional, output local endpoint object on which to queue endpoint operations.
Return value
PartyError
c_partyErrorSuccess if the asynchronous operation to create the endpoint began, or an error code otherwise. If
this method fails, no related state changes will be generated. The human-readable form of the error code can be
retrieved via PartyManager::GetErrorMessage().

Remarks
This method queues an asynchronous attempt to create an endpoint associated with the local device on this
network. A PartyCreateEndpointCompletedStateChange will be provided upon completion of the operation,
indicating success or failure. On success, a PartyEndpointCreatedStateChange will be generated, and the
endpoint will be fully created, connected to the network, and visible to all authenticated devices in the network.
On failure, a PartyEndpointDestroyedStateChange will be generated.

This method optionally provides localEndpoint as output that can immediately be used to perform
asynchronous endpoint operations, such as PartyLocalEndpoint::SendMessage() and
PartyLocalEndpoint::SetSharedProperties(). These asynchronous operations will be internally queued until the
endpoint creation completes, at which point they will be processed. PartyEndpoint::GetUniqueIdentifier() will
return a failure until the endpoint creation completes. This localEndpoint will also be provided in the resulting
PartyCreateEndpointCompletedStateChange.

A local user may optionally be provided as the owner of an endpoint. If an owning local user is provided, it must
be authenticated into the network or in the process of authenticating into the network. If its authentication fails,
the endpoint creation will consequently fail as well. If the owning local user is removed from the network while
this endpoint exists, the endpoint will be automatically destroyed. This will be signaled via a
PartyEndpointDestroyedStateChange.

If the local device enters a state in which there are no authenticated users and no authentication operations in
progress, then all endpoints, including those that are not fully created, will be destroyed automatically. This will
be signaled by PartyEndpointDestroyedStateChanges.

On successful return, this method invalidates the memory for any array previously returned by GetEndpoints(),
as it synchronously adds the new endpoint to the array. PartyManager::StartProcessingStateChanges() also
invalidates the memory for the array. The returned localEndpoint object will be valid until a
PartyEndpointDestroyedStateChange has been generated and all state changes referencing the object have been
returned to PartyManager::FinishProcessingStateChanges().

The property bag is a collection of title-specific values associated with an endpoint. The initial property bag is
queryable as soon as the endpoint becomes visible.

The property bag is currently unimplemented. propertyCount must be zero and both keys and values must
be nullptr.

If a client would violate the PartyNetworkConfiguration::maxEndpointsPerDeviceCount limit by calling this


method after the network configuration was made available, this operation will fail synchronously. If the client
queues a violating number of endpoint creations before the network configuration becomes available, the client
will be kicked from the network and a PartyNetworkDestroyedStateChange will be generated when the network
configuration becomes available.

Requirements
Header : Party.h
See also
PartyNetwork
PartyCreateEndpointCompletedStateChange
PartyEndpointCreatedStateChange
PartyEndpointDestroyedStateChange
PartyNetworkDestroyedStateChange
PartyNetworkConfiguration
PartyNetwork::GetEndpoints
PartyLocalEndpoint::SendMessage
PartyEndpoint::GetUniqueIdentifier
PartyEndpoint::GetEntityId
PartyNetwork::AuthenticateLocalUser
PartyNetwork::RemoveLocalUser
PartyNetwork::DestroyEndpoint
5/24/2022 • 2 minutes to read • Edit Online

Queues an asynchronous operation to destroy a local endpoint.

Syntax
PartyError DestroyEndpoint(
PartyLocalEndpoint* localEndpoint,
void* asyncIdentifier
)

Parameters
localEndpoint PartyLocalEndpoint*
The local endpoint to begin destroying.
asyncIdentifier void*
optional
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
Return value
PartyError
c_partyErrorSuccess if the asynchronous operation to destroy the endpoint began, or an error code otherwise.
If this method fails, no related state changes will be generated. The human-readable form of the error code can
be retrieved via PartyManager::GetErrorMessage().

Remarks
This method queues an asynchronous operation to destroy an endpoint associated with the local device on this
network. A PartyDestroyEndpointCompletedStateChange will be provided upon completion of the operation,
indicating success or failure. On success, the endpoint is no longer connected to the network or visible to any
devices. Memory for the endpoint will remain valid until all state changes referencing the endpoint have been
returned to PartyManager::FinishProcessingStateChanges().

If this call returns success, asynchronous endpoint destruction has begun and methods that attempt to send
data from this local endpoint to the Party network, such as PartyLocalEndpoint::SendMessage() and
PartyLocalEndpoint::FlushMessages(), will fail. Methods that retrieve cached state, such as
PartyEndpoint::GetCustomContext() and PartyEndpoint::GetEntityId(), will continue to succeed.

When the local device begins destroying an endpoint, every remote device will be alerted via a
PartyEndpointDestroyedStateChange. Those remote devices have the opportunity to send the destructing
endpoint any final messages they wish before returning the PartyEndpointDestroyedStateChange to
PartyManager::FinishProcessingStateChanges(). By returning the PartyEndpointDestroyedStateChange, the
remote device acknowledges the endpoint's destruction and may no longer target the endpoint in
PartyLocalEndpoint::SendMessage() calls. Because the endpoint will not be able to complete its destruction on
the local device until all remote devices have acknowledged it, it is recommended to return this state change as
quickly as possible. If the remote device does not return the PartyEndpointDestroyedStateChange within two
seconds, the remote device will automatically acknowledge the endpoint destruction and the endpoint will no
longer be targetable in PartyLocalEndpoint::SendMessage() calls. The destructing endpoint can receive
PartyEndpointMessageReceivedStateChanges up until all remote devices have acknowledged the endpoint's
destruction, which is indicated by a PartyEndpointDestroyedStateChange generated on the local device.

Requirements
Header : Party.h

See also
PartyNetwork
PartyDestroyEndpointCompletedStateChange
PartyEndpointDestroyedStateChange
PartyEndpointMessageReceivedStateChange
PartyLocalEndpoint::SendMessage
PartyEndpoint::GetCustomContext
PartyEndpoint::GetEntityId
PartyNetwork::LeaveNetwork
5/24/2022 • 2 minutes to read • Edit Online

Queues an asynchronous operation to leave the network gracefully.

Syntax
PartyError LeaveNetwork(
void* asyncIdentifier
)

Parameters
asyncIdentifier void*
optional
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
Return value
PartyError
c_partyErrorSuccess if the asynchronous operation to leave the network began, or an error code otherwise. If
this method fails, no related state changes will be generated. The human-readable form of the error code can be
retrieved via PartyManager::GetErrorMessage().

Remarks
This method queues an asynchronous operation to gracefully leave the network. A
PartyLeaveNetworkCompletedStateChange will be provided upon completion of the operation, indicating
success or failure. Memory for the network will remain valid until all state changes referencing the network have
been returned to PartyManager::FinishProcessingStateChanges().

Before successful completion of the operation, all in-flight inbound and outbound traffic to and from all local
endpoints on this device will be delivered, state changes will be generated on this device showing all local and
remote endpoints being destroyed (each indicated by a PartyEndpointDestroyedStateChange), all chat controls
being disconneced from this network (each indicated by a PartyChatControlLeftNetworkStateChange), all
remote devices leaving the network (each indicated by a PartyRemoteDeviceLeftNetworkStateChange), and all
local users being removed from this network (each indicated by a PartyLocalUserRemovedStateChange).

This object will be valid until a PartyNetworkDestroyedStateChange has been generated and all state changes
referencing the object have been returned to PartyManager::FinishProcessingStateChanges().

Requirements
Header : Party.h

See also
PartyNetwork
PartyNetworkDestroyedStateChange
PartyEndpointDestroyedStateChange
PartyChatControlLeftNetworkStateChange
PartyRemoteDeviceLeftNetworkStateChange
PartyLocalUserRemovedStateChange
PartyNetwork::GetEndpoints
5/24/2022 • 2 minutes to read • Edit Online

Gets the endpoints in this network.

Syntax
PartyError GetEndpoints(
uint32_t* endpointCount,
PartyEndpointArray* endpoints
)

Parameters
endpointCount uint32_t*
output
The output number of PartyEndpoint entries in the endpoints array.
endpoints PartyEndpointArray*
library-allocated output array of size *endpointCount

A library-allocated output array containing the endpoints in this network.


Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
This method gets all endpoints currently associated with the network and visible to the local device.

All local endpoints that have successfully been created or are in the process of being created will be present in
endpoints . All remote endpoints that have been successfully created will also be present.

Once a PartyEndpointDestroyedStateChange has been provided by


PartyManager::StartProcessingStateChanges(), the endpoint will no longer be present in the array returned by
this method.

The memory for the returned array is invalidated whenever the title calls
PartyManager::StartProcessingStateChanges() or CreateEndpoint() returns success.

Requirements
Header : Party.h

See also
PartyNetwork
PartyEndpointCreatedStateChange
PartyEndpointDestroyedStateChange
PartyNetwork::CreateEndpoint
PartyNetwork::FindEndpointByUniqueIdentifier
5/24/2022 • 2 minutes to read • Edit Online

Finds the endpoint with the corresponding network-unique identifier in this network, if it exists.

Syntax
PartyError FindEndpointByUniqueIdentifier(
uint16_t uniqueIdentifier,
PartyEndpoint** endpoint
)

Parameters
uniqueIdentifier uint16_t
The network-unique identifier of an endpoint.
endpoint PartyEndpoint**
library-allocated output
The output endpoint with a network-unique identifier matching uniqueIdentifier .
Return value
PartyError
c_partyErrorSuccessif an endpoint with a matching identifier was found on this network or an error code
otherwise. The human-readable form of the error code can be retrieved via PartyManager::GetErrorMessage().

Remarks
This method returns an error if the endpoint is not valid on the local device, that is, if the
PartyEndpointCreatedStateChange for the endpoint associated with uniqueIdentifier has not yet been
provided by PartyManager::StartProcessingStateChanges() or if the PartyEndpointDestroyedStateChange has
been generated and all state changes referencing the endpoint have been returned to
PartyManager::FinishProcessingStateChanges().

All devices in a network will agree on a given endpoint's unique identifier, but different devices may not see the
same endpoints at a given moment. For example, it's possible for endpoint A to send a message to endpoint B
that references a newly-created endpoint C's unique identifier, but that message between A and B may arrive
before the PartyEndpointCreatedStateChange for endpoint C is generated on endpoint B's device. In that
situation, this method will return an error when called on endpoint B's device because endpoint C is not yet
known on that device.

Requirements
Header : Party.h

See also
PartyNetwork
PartyEndpoint::GetUniqueIdentifier
PartyEndpointCreatedStateChange
PartyEndpointDestroyedStateChange
PartyNetwork::GetDevices
5/24/2022 • 2 minutes to read • Edit Online

Gets the devices in this network.

Syntax
PartyError GetDevices(
uint32_t* deviceCount,
PartyDeviceArray* devices
)

Parameters
deviceCount uint32_t*
output
The output number of devices in this network.
devices PartyDeviceArray*
library-allocated output array of size *deviceCount

A library-allocated output array containing the devices in this network.


Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
Once a PartyRemoteDeviceLeftNetworkStateChange has been provided by
PartyManager::StartProcessingStateChanges(), the remote device will no longer be present in the array returned
by this method. The local device is always in the array.

The memory for the returned array is invalidated whenever the title calls
PartyManager::StartProcessingStateChanges().

Requirements
Header : Party.h

See also
PartyNetwork
PartyRemoteDeviceLeftNetworkStateChange
PartyNetwork::GetLocalUsers
5/24/2022 • 2 minutes to read • Edit Online

Gets an array containing the local users that are authenticated or authenticating into the network.

Syntax
PartyError GetLocalUsers(
uint32_t* userCount,
PartyLocalUserArray* localUsers
)

Parameters
userCount uint32_t*
output
An output value indicating the number of users provided in localUsers .
localUsers PartyLocalUserArray*
library-allocated output array of size *userCount

A library-allocated output array containing the local users that are authenticated or authenticating into the
network.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
Once a PartyLocalUserRemovedStateChange has been provided by
PartyManager::StartProcessingStateChanges(), the local user will no longer be present in the array returned by
this method.

The memory for the returned array is invalidated whenever the title calls
PartyManager::StartProcessingStateChanges() or AuthenticateLocalUser() returns success.

Requirements
Header : Party.h

See also
PartyNetwork
PartyNetwork::AuthenticateLocalUser
PartyNetwork::RemoveLocalUser
PartyLocalUserRemovedStateChange
PartyNetwork::GetNetworkDescriptor
5/24/2022 • 2 minutes to read • Edit Online

Gets the network descriptor for this network.

Syntax
PartyError GetNetworkDescriptor(
PartyNetworkDescriptor* networkDescriptor
)

Parameters
networkDescriptor PartyNetworkDescriptor*
output
The output network descriptor.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
A network descriptor contains all the information required for a device to connect to the network to which the
descriptor is associated. PartyManager::SerializeNetworkDescriptor() can be used to get the serialized form of
the descriptor, which is safe to exchange over title and platform-specific communication channels. However, the
network descriptor provided by this call is not serializable until the asynchronous creation operation associated
with this network successfully completes, signaled by a PartyCreateNewNetworkCompletedStateChange with a
success result code.

PartyNetworkDescriptors work in tandem with PartyInvitations to facilitate inviting remote users to join the
network. First, obtain the network descriptor via GetNetworkDescriptor() and serialize it via
PartyManager::SerializeNetworkDescriptor(). Next, create an invitation via CreateInvitation() or query for a
preexisting invitation via GetInvitations() and obtain the invitation's identifier from its configuration via
PartyInvitation::GetInvitationConfiguration(). Last, include both the serialized network descriptor and the
invitation identifier in the payload of the platform-specific invite mechanism. When the remote user receives the
invite, they deserialize the network descriptor from the platform-invite payload via
PartyManager::DeserializeNetworkDescriptor() and pass the deserialized descriptor to
PartyManager::ConnectToNetwork(). After connecting, the remote user joins by authenticating into the network
via AuthenticateLocalUser() with the invitation identifier in the platform-invite payload.

Requirements
Header : Party.h

See also
PartyNetwork
PartyCreateNewNetworkCompletedStateChange
PartyManager::CreateNewNetwork
PartyManager::SerializeNetworkDescriptor
PartyManager::DeserializeNetworkDescriptor
PartyManager::ConnectToNetwork
PartyInvitation
PartyNetwork::CreateInvitation
PartyNetwork::GetInvitations
PartyInvitation::GetInvitationConfiguration
PartyNetwork::AuthenticateLocalUser
PartyNetwork::GetNetworkConfiguration
5/24/2022 • 2 minutes to read • Edit Online

Gets the network configuration which was set when creating the network.

Syntax
PartyError GetNetworkConfiguration(
const PartyNetworkConfiguration** networkConfiguration
)

Parameters
networkConfiguration PartyNetworkConfiguration**
library-allocated output
The output network configuration.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
This method returns an error until PartyManager::StartProcessingStateChanges() provides a
PartyNetworkConfigurationMadeAvailableStateChange.

Requirements
Header : Party.h

See also
PartyNetwork
PartyNetworkConfigurationMadeAvailableStateChange
PartyNetwork::ConnectChatControl
5/24/2022 • 2 minutes to read • Edit Online

Connects the local chat control to the network.

Syntax
PartyError ConnectChatControl(
PartyLocalChatControl* chatControl,
void* asyncIdentifier
)

Parameters
chatControl PartyLocalChatControl*
The chat control to connect to this network.
asyncIdentifier void*
optional
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
Return value
PartyError
c_partyErrorSuccess if the asynchronous operation to connect the chat control began, or an error code
otherwise. If this method fails, no related state changes will be generated. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
On successful return, this method invalidates the memory for any array previously returned by
GetChatControls() or PartyChatControl::GetNetworks() for chatControl , as it synchronously updates those
arrays. PartyManager::StartProcessingStateChanges() also invalidates the memory for those arrays.

Requirements
Header : Party.h

See also
PartyNetwork
PartyNetwork::DisconnectChatControl
5/24/2022 • 2 minutes to read • Edit Online

Disconnects the local chat control from the network.

Syntax
PartyError DisconnectChatControl(
PartyLocalChatControl* chatControl,
void* asyncIdentifier
)

Parameters
chatControl PartyLocalChatControl*
The chat control to disconnect from this network.
asyncIdentifier void*
optional
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
Return value
PartyError
c_partyErrorSuccess if the asynchronous operation to disconnect the chat control began, or an error code
otherwise. If this method fails, no related state changes will be generated. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Requirements
Header : Party.h

See also
PartyNetwork
PartyNetwork::GetChatControls
5/24/2022 • 2 minutes to read • Edit Online

Gets the chat controls connected to this network.

Syntax
PartyError GetChatControls(
uint32_t* chatControlCount,
PartyChatControlArray* chatControls
)

Parameters
chatControlCount uint32_t*
output
The output number of chat controls in this network.
chatControls PartyChatControlArray*
library-allocated output array of size *chatControlCount
A library-allocated output array containing the chat controls in this network.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
Once a PartyChatControlLeftNetworkStateChange has been generated for a chat control by
PartyManager::StartProcessingStateChanges(), the chat control will no longer be present in the array returned
by this method.

The memory for the returned array is invalidated whenever the title calls
PartyManager::StartProcessingStateChanges() or ConnectChatControl() returns success.

Requirements
Header : Party.h

See also
PartyNetwork
PartyNetwork::ConnectChatControl
PartyNetwork::DisconnectChatControl
PartyChatControlLeftNetworkStateChange
PartyNetwork::GetNetworkStatistics
5/24/2022 • 2 minutes to read • Edit Online

Gets one or more statistic counter values for the network.

Syntax
PartyError GetNetworkStatistics(
uint32_t statisticCount,
const PartyNetworkStatistic* statisticTypes,
uint64_t* statisticValues
)

Parameters
statisticCount uint32_t
The number of statistics in the input statisticTypes array and to be written in the statisticValues output
array. This must be at least 1.
statisticTypes PartyNetworkStatistic*
input array of size statisticCount
The statisticCount entry input array of unique PartyNetworkStatistic types to retrieve.
statisticValues uint64_t*
output array of size statisticCount
The statisticCount entry output array where the statistic values should be written. Each statistic value will be
written at the same entry index corresponding to where the requested PartyNetworkStatistic appears in the
statisticTypes input array.

Return value
PartyError
c_partyErrorSuccess if retrieving the network statistics succeeded or an error code otherwise. The human-
readable form of the error code can be retrieved via PartyManager::GetErrorMessage().

Remarks
This method is used to retrieve performance counters, queue lengths, historical usage metrics, or other
statistical information recorded for this network.

A given PartyNetworkStatistic type may appear in any order in the statisticTypes array, but must not be
specified more than once. Each corresponding statistic value will be written to the statisticValues array in the
same order.

The returned statistic values are always the most current ones available. There is no guarantee they will report
the same value from one GetNetworkStatistics() call to the next, even if there were no intervening calls to
PartyManager::StartProcessingStateChanges() or PartyManager::FinishProcessingStateChanges().

Requirements
Header : Party.h

See also
PartyNetwork
PartyNetworkStatistic
PartyLocalEndpoint::GetEndpointStatistics
PartyNetwork::GetCustomContext
5/24/2022 • 2 minutes to read • Edit Online

Retrieves the app's private, custom pointer-sized context value previously associated with this network object.

Syntax
PartyError GetCustomContext(
void** customContext
)

Parameters
customContext void**
output, may return nullptr
The output custom context.
Return value
PartyError
c_partyErrorSuccess if retrieving the custom context succeeded or an error code otherwise. The human-
readable form of the error code can be retrieved via PartyManager::GetErrorMessage().

Remarks
If no custom context has been set yet, the value pointed to by customContext is set to nullptr.

Requirements
Header : Party.h

See also
PartyNetwork
PartyNetwork::SetCustomContext
PartyNetwork::SetCustomContext
5/24/2022 • 2 minutes to read • Edit Online

Configures an optional, custom pointer-sized context value with this network object.

Syntax
PartyError SetCustomContext(
void* customContext
)

Parameters
customContext void*
optional
An arbitrary, pointer-sized value to store with the network object.
Return value
PartyError
c_partyErrorSuccess if configuring the custom context succeeded or an error code otherwise. The human-
readable form of the error code can be retrieved via PartyManager::GetErrorMessage().

Remarks
The custom context is typically used as a "shortcut" that simplifies accessing local, title-specific memory
associated with the network without requiring a mapping lookup. The value is retrieved using the
GetCustomContext() method.

Any configured value is treated as opaque by the library, and is only valid on the local device; it is not
transmitted over the network.

Requirements
Header : Party.h

See also
PartyNetwork
PartyNetwork::GetCustomContext
PartyNetwork::GetDeviceConnectionType
5/24/2022 • 2 minutes to read • Edit Online

Retrieves the type of connection used by the local device for transmitting messages or chat data to the specified
target device in this network.

Syntax
PartyError GetDeviceConnectionType(
const PartyDevice* targetDevice,
PartyDeviceConnectionType* deviceConnectionType
)

Parameters
targetDevice PartyDevice*
The device whose connection type should be retrieved.
deviceConnectionType PartyDeviceConnectionType*
output
The output device connection type.
Return value
PartyError
c_partyErrorSuccess if retrieving the connection type succeeded or an error code otherwise. The human-
readable form of the error code can be retrieved via PartyManager::GetErrorMessage().

Remarks
Connection types are determined when devices first authenticate an initial user into the network. If this network
permitted direct peer-to-peer connectivity via the PartyNetworkConfiguration::directPeerConnectivityOptions
field, neither device had excluded such connectivity via the
PartyOption::LocalDeviceDirectPeerConnectivityOptionsMask option, and a direct peer connection was
successfully established at that time, then this function will report a value of
PartyDeviceConnectionType::DirectPeerConnection. Otherwise it will report
PartyDeviceConnectionType::RelayServer. The value will not change for as long as the target PartyDevice object
remains in this network, even if PartyNetwork::RemoveLocalUser() is called for that initially authenticating user.

If the target device is the local device, PartyDeviceConnectionType::DirectPeerConnection will always be reported
regardless of PartyNetworkConfiguration settings or
PartyOption::LocalDeviceDirectPeerConnectivityOptionsMask option.

If the target device object is not participating in this network, an error is returned.

If the local device is participating in additional networks with the target device object, you should not assume
that calling this same function on those other network objects will report the same value.

Requirements
Header : Party.h

See also
PartyNetwork
PartyDeviceConnectionType
PartyNetworkConfiguration
PartyOption::LocalDeviceDirectPeerConnectivityOptionsMask
PartyTextToSpeechProfile
5/24/2022 • 2 minutes to read • Edit Online

Represents the voice profile used to synthesize speech.

Syntax
class PartyTextToSpeechProfile

Public Methods
NAME DESC RIP T IO N

GetIdentifier Gets the unique identifier associated with this profile.

GetName Gets the human-readable name of this profile.

GetLanguageCode Gets the language code associated with this profile.

GetGender Gets the gender associated with this profile.

GetCustomContext Retrieves the app's private, custom pointer-sized context


value previously associated with this profile.

SetCustomContext Configures an optional, custom pointer-sized context value


with this profile.

Requirements
Header : Party.h

See also
Party members
PartyLocalChatControl::PopulateAvailableTextToSpeechProfiles
PartyLocalChatControl::GetAvailableTextToSpeechProfiles
PartyLocalChatControl::SetTextToSpeechProfile
PartyLocalChatControl::GetTextToSpeechProfile
PartyTextToSpeechProfile::GetIdentifier
5/24/2022 • 2 minutes to read • Edit Online

Gets the unique identifier associated with this profile.

Syntax
PartyError GetIdentifier(
PartyString* identifier
)

Parameters
identifier PartyString*
library-allocated output
The output unique identifier. The memory for the string remains valid for the lifetime of the profile.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Requirements
Header : Party.h

See also
PartyTextToSpeechProfile
PartyLocalChatControl::SetTextToSpeechProfile
PartyTextToSpeechProfile::GetName
5/24/2022 • 2 minutes to read • Edit Online

Gets the human-readable name of this profile.

Syntax
PartyError GetName(
PartyString* name
)

Parameters
name PartyString*
library-allocated output
The output profile name. The memory for the string remains valid for the lifetime of the profile.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Remarks
This name is intended for use in title UI and logs, but is not localized.

Requirements
Header : Party.h

See also
PartyTextToSpeechProfile
PartyTextToSpeechProfile::GetLanguageCode
5/24/2022 • 2 minutes to read • Edit Online

Gets the language code associated with this profile.

Syntax
PartyError GetLanguageCode(
PartyString* languageCode
)

Parameters
languageCode PartyString*
library-allocated output
The output profile language. The memory for the string remains valid for the lifetime of the profile.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Requirements
Header : Party.h

See also
PartyTextToSpeechProfile
PartyTextToSpeechProfile::GetGender
5/24/2022 • 2 minutes to read • Edit Online

Gets the gender associated with this profile.

Syntax
PartyError GetGender(
PartyGender* gender
)

Parameters
gender PartyGender*
output
The output profile gender.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyManager::GetErrorMessage().

Requirements
Header : Party.h

See also
PartyTextToSpeechProfile
PartyTextToSpeechProfile::GetCustomContext
5/24/2022 • 2 minutes to read • Edit Online

Retrieves the app's private, custom pointer-sized context value previously associated with this profile.

Syntax
PartyError GetCustomContext(
void** customContext
)

Parameters
customContext void**
output, may return nullptr
The output custom context.
Return value
PartyError
c_partyErrorSuccess if retrieving the custom context succeeded or an error code otherwise. The human-
readable form of the error code can be retrieved via PartyManager::GetErrorMessage().

Remarks
If no custom context has been set yet, the value pointed to by customContext is set to nullptr.

Requirements
Header : Party.h

See also
PartyTextToSpeechProfile
PartyTextToSpeechProfile::SetCustomContext
PartyTextToSpeechProfile::SetCustomContext
5/24/2022 • 2 minutes to read • Edit Online

Configures an optional, custom pointer-sized context value with this profile.

Syntax
PartyError SetCustomContext(
void* customContext
)

Parameters
customContext void*
optional
An arbitrary, pointer-sized value to store with the profile object.
Return value
PartyError
c_partyErrorSuccess if configuring the custom context succeeded or an error code otherwise. The human-
readable form of the error code can be retrieved via PartyManager::GetErrorMessage().

Remarks
The custom context is typically used as a "shortcut" that simplifies accessing local, title-specific memory
associated with the profile without requiring a mapping lookup. The value is retrieved using the
GetCustomContext() method.

Any configured value is treated as opaque by the library, and is only valid on the local device; it is not
transmitted over the network.

Requirements
Header : Party.h

See also
PartyTextToSpeechProfile
PartyTextToSpeechProfile::GetCustomContext
PartyAllocateMemoryCallback
5/24/2022 • 2 minutes to read • Edit Online

A callback invoked every time a new memory buffer must be dynamically allocated by the Party library.

Syntax
typedef
void* (*PartyAllocateMemoryCallback)(
size_t size,
uint32_t memoryTypeId
)

Parameters
size size_t

The size of the allocation to be made. This value will never be zero.
memoryTypeId uint32_t
An opaque identifier representing the Party library internal category of memory being allocated. This value
should be ignored.
Return value
Type: void*
A pointer to an allocated block of memory of the specified size, or nullptr if the allocation failed.

Remarks
This callback is optionally installed using the PartyManager::SetMemoryCallbacks() method.

The callback must allocate and return a pointer to a contiguous block of memory of the specified size that will
remain valid until the title's corresponding PartyFreeMemoryCallback is invoked to release it. If this is not
possible, the callback must return nullptr to fail the allocation. Memory allocation failures are sometimes
considered benign but will usually cause current Party library operation(s) to fail.

Every non-nullptr returned by this method will be subsequently passed to the corresponding
PartyFreeMemoryCallback once the memory is no longer needed.

Requirements
Header : Party.h

See also
Party members
PartyFreeMemoryCallback
PartyManager::SetMemoryCallbacks
PartyManager::GetMemoryCallbacks
PartyFreeMemoryCallback
5/24/2022 • 2 minutes to read • Edit Online

A callback invoked every time a previously allocated memory buffer is no longer needed by the Party library
and can be freed.

Syntax
typedef
void (*PartyFreeMemoryCallback)(
void* pointer,
uint32_t memoryTypeId
)

Parameters
pointer void*
Post_invalid
A pointer to a memory buffer previously allocated. This value will never be nullptr.
memoryTypeId uint32_t
An opaque identifier representing the Party library internal category of memory being freed. This value should
be ignored.
Return value
Type: void
The callback does not return a value.

Remarks
This callback is optionally installed using the PartyManager::SetMemoryCallbacks() method.

The callback is invoked whenever the Party library has finished using a memory buffer previously returned by
the title's corresponding PartyAllocateMemoryCallback, so that the title can free the memory buffer.

Requirements
Header : Party.h

See also
Party members
PartyAllocateMemoryCallback
PartyManager::SetMemoryCallbacks
PartyManager::GetMemoryCallbacks
PartyProfilingMethodEntranceCallback
5/24/2022 • 2 minutes to read • Edit Online

A callback invoked every time the Party library enters an instrumented method.

Syntax
typedef
void (*PartyProfilingMethodEntranceCallback)(
const PartyProfilingMethodEntranceEventData* eventData
)

Parameters
eventData PartyProfilingMethodEntranceEventData*
A constant pointer to a structure containing additional information which may be of use when profiling this
event. The data referenced by this pointer is guaranteed to be valid only for the duration the callback.
Return value
Type: void
The callback does not return a value.

Remarks
This callback is optionally installed using the PartyManager::SetProfilingCallbacksForMethodEntryExit() method,
which also details the types of profiled events available to a caller.

In order to minimize the impact of profiling on title performance, callbacks should be kept as lightweight as
possible as they are expected to fire hundreds or thousands of times per second.

Requirements
Header : Party.h

See also
Party members
PartyProfilingMethodEntranceEventData
PartyManager::SetProfilingCallbacksForMethodEntryExit
PartyManager::GetProfilingCallbacksForMethodEntryExit
PartyProfilingMethodExitCallback
5/24/2022 • 2 minutes to read • Edit Online

A callback invoked every time the Party library is about to exit an instrumented method.

Syntax
typedef
void (*PartyProfilingMethodExitCallback)(
const PartyProfilingMethodExitEventData* eventData
)

Parameters
eventData PartyProfilingMethodExitEventData*
A constant pointer to a structure containing additional information which may be of use when profiling this
event. The data referenced by this pointer is guaranteed to be valid only for the duration the callback.
Return value
Type: void
The callback does not return a value.

Remarks
This callback is optionally installed using the PartyManager::SetProfilingCallbacksForMethodEntryExit() method,
which also details the types of profiled events available to a caller.

In order to minimize the impact of profiling on title performance, callbacks should be kept as lightweight as
possible as they are expected to fire hundreds or thousands of times per second.

Requirements
Header : Party.h

See also
Party members
PartyProfilingMethodExitEventData
PartyManager::SetProfilingCallbacksForMethodEntryExit
PartyManager::GetProfilingCallbacksForMethodEntryExit
PartyAudioFormat
5/24/2022 • 2 minutes to read • Edit Online

The format information needed to interpret Party audio data.

Syntax
struct PartyAudioFormat {
uint32_t samplesPerSecond;
uint32_t channelMask;
uint16_t channelCount;
uint16_t bitsPerSample;
PartyAudioSampleType sampleType;
PartyBool interleaved;
}

Members
samplesPerSecond uint32_t
Specifies the sample frequency at which each channel should be played or recorded.
channelMask uint32_t
Overrides the assignment of channels in a multichannel audio stream to speaker positions.
channelCount uint16_t
Specifies the number of channels of audio data.
bitsPerSample uint16_t
Specifies the number of bits per sample. If this value is not byte-divisible, it will be assumed that the containing
sample type is padded with bits to make it byte-divisble.
sampleType PartyAudioSampleType
Specifies the sample type.
interleaved PartyBool
A flag representing whether the multichannel audio data is interleaved for multi-channel formats.

Requirements
Header : Party.h

See also
Party members
PartyAudioManipulationSinkStreamConfiguration
5/24/2022 • 2 minutes to read • Edit Online

The configuration information needed to set up an audio sink stream.

Syntax
struct PartyAudioManipulationSinkStreamConfiguration {
PartyAudioFormat* format;
uint32_t maxTotalAudioBufferSizeInMilliseconds;
}

Members
format PartyAudioFormat*
may be nullptr
Optionally specifies the format of the audio that will be submitted to the sink stream.
If this value is nullptr, the sink stream will be configured to use the format most efficient for the library. The
format can be queried via PartyAudioManipulationSinkStream::GetFormat().
maxTotalAudioBufferSizeInMilliseconds uint32_t
The maximum total size of audio buffers that can concurrently exist for this queue, in milliseconds.
This defines the limit for the total amount of audio internally queued by the sink stream, but not yet processed
by the library. When this limit is reached, the sink stream will stop accepting additional buffers.

This value should be chosen based on how frequently the game will submit buffers to the sink stream and how
large those buffers will be. Because the library processes audio in 40 milliseconds intervals, the minimum is 40
milliseconds. Most games will find 200 milliseconds to be a reasonable value.

Requirements
Header : Party.h

See also
Party members
PartyLocalChatControl::ConfigureAudioManipulationCaptureStream
PartyLocalChatControl::ConfigureAudioManipulationRenderStream
PartyAudioManipulationSourceStreamConfiguration
5/24/2022 • 2 minutes to read • Edit Online

The configuration information needed to set up an audio source stream.

Syntax
struct PartyAudioManipulationSourceStreamConfiguration {
PartyAudioFormat* format;
uint32_t maxTotalAudioBufferSizeInMilliseconds;
}

Members
format PartyAudioFormat*
may be nullptr
Optionally specifies the format of the audio that should be produced by the source stream.
If this value is nullptr, the source stream will produce audio in the format most efficient for the library. The
format can be queried via PartyAudioManipulationSourceStream::GetFormat().
maxTotalAudioBufferSizeInMilliseconds uint32_t
The maximum total size of audio buffers that can concurrently exist for this queue, in milliseconds.
This defines the limit for the total amount of audio internally queued by the source stream, but not yet retrieved
via PartyAudioManipulationSourceStream::GetNextBuffer, plus the total amount of audio retrieved by the app,
but not yet returned to the library via PartyAudioManipulationSourceStream::ReturnBuffer. When this total is
reached, the source stream will stop producing additional buffers.

Because the library processes audio in 40 millisecond intervals, the effective maximum is the nearest multiple of
40 less than the specified maximum. The minimum is 40 milliseconds.

Requirements
Header : Party.h

See also
Party members
PartyChatControl::ConfigureAudioManipulationVoiceStream
PartyDataBuffer
5/24/2022 • 2 minutes to read • Edit Online

A data buffer.

Syntax
struct PartyDataBuffer {
const void* buffer;
uint32_t bufferByteCount;
}

Members
buffer const void*
buffer of size bufferByteCount bytes
The data buffer.
bufferByteCount uint32_t
The size of the buffer in bytes.

Requirements
Header : Party.h

See also
Party members
PartyInvitationConfiguration
5/24/2022 • 2 minutes to read • Edit Online

Invitation configuration data.

Syntax
struct PartyInvitationConfiguration {
PartyString identifier;
PartyInvitationRevocability revocability;
uint32_t entityIdCount;
const PartyString* entityIds;
}

Members
identifier PartyString
may be nullptr
The identifier of the invitation.
This value may only be nullptr when used as input to PartyManager::CreateNewNetwork() or
PartyNetwork::CreateInvitation().

The length of this string must be less than or equal to c_maxInvitationIdentifierStringLength .


revocability PartyInvitationRevocability
The revocability of the invitation.
entityIdCount uint32_t
The number of PlayFab Entity IDs that the invitation allows to authenticate into the network.
If this value is 0, all users are allowed to authenticate using the invitation's identifier.

This value must be less than or equal to c_maxInvitationEntityIdCount .


entityIds const PartyString*
array of size entityIdCount

The list of PlayFab Entity IDs that the invitation allows to authenticate into the network.
If this list is empty, all users are allowed to authenticate using the invitation's identifier.

Requirements
Header : Party.h

See also
Party members
PartyInvitation
PartyInvitationRevocability
PartyManager::CreateNewNetwork
PartyNetwork::CreateInvitation
PartyInvitation::GetInvitationConfiguration
PartyLocalUdpSocketBindAddressConfiguration
5/24/2022 • 2 minutes to read • Edit Online

The configuration used by the Party library to bind to a UDP socket.

Syntax
struct PartyLocalUdpSocketBindAddressConfiguration {
PartyLocalUdpSocketBindAddressOptions options;
uint16_t port;
}

Members
options PartyLocalUdpSocketBindAddressOptions
Optional flags describing how to interpret this UDP socket configuration.
port uint16_t
The specific port number to which the local UDP socket will be bound the next time Party is initialized.
In the Microsoft Game Core version of the Party library, a port value of 0 means that the Party library will select
the Game Core preferred local UDP multiplayer port unless the
PartyLocalUdpSocketBindAddressOptions::ExcludeGameCorePreferredUdpMultiplayerPort option flag is
specified in the options field. On all other versions of the Party library, a port value of 0 means the Party library
will let the system dynamically select a port that's available on all local IP address interfaces.

If this port value cannot be bound when the Party library is initialized, PartyManager::Initialize() will
synchronously return an error. The human-readable form of the error code can be retrieved via
PartyManager::GetErrorMessage().

The port should be specified in native host byte order. If your application also directly uses or is porting from its
own socket API calls, be aware that this natural byte ordering may therefore differ from the network byte order
used by socket address port numbers.

The default value is 0 when PartyOption::LocalUdpSocketBindAddress has not been configured.

Remarks
This structure can be used together with PartyOption::LocalUdpSocketBindAddress to either override or query
the Party library's current configuration via PartyManager::SetOption() and PartyManager::GetOption()
respectively.

Requirements
Header : Party.h

See also
Party members
PartyOption::LocalUdpSocketBindAddress
PartyLocalUdpSocketBindAddressOptions
PartyManager::SetOption
PartyManager::GetOption
PartyMutableDataBuffer
5/24/2022 • 2 minutes to read • Edit Online

A data buffer that can be modified by the app.

Syntax
struct PartyMutableDataBuffer {
void* buffer;
uint32_t bufferByteCount;
}

Members
buffer void*
buffer of size bufferByteCount bytes
The data buffer.
bufferByteCount uint32_t
The size of the buffer in bytes.

Requirements
Header : Party.h

See also
Party members
PartyNetworkConfiguration
5/24/2022 • 4 minutes to read • Edit Online

Network configuration data.

Syntax
struct PartyNetworkConfiguration {
uint32_t maxUserCount;
uint32_t maxDeviceCount;
uint32_t maxUsersPerDeviceCount;
uint32_t maxDevicesPerUserCount;
uint32_t maxEndpointsPerDeviceCount;
PartyDirectPeerConnectivityOptions directPeerConnectivityOptions;
}

Members
maxUserCount uint32_t
The maximum number of unique users allowed in the network.
This value must be greater than 0.

If a client would violate this limit by calling PartyNetwork::AuthenticateLocalUser(), the operation will fail
asynchronously and PartyAuthenticateLocalUserCompletedStateChange::result will be set to
PartyStateChangeResult::NetworkLimitReached.
maxDeviceCount uint32_t
The maximum number of devices allowed to connect to the network.
This value must be between 1 and c_maxNetworkConfigurationMaxDeviceCount inclusive.

If a client would violate this limit by calling PartyManager::ConnectToNetwork(), the operation will fail
asynchronously and PartyConnectToNetworkCompletedStateChange::result will be set to
PartyStateChangeResult::NetworkLimitReached.
maxUsersPerDeviceCount uint32_t
The maximum number of users allowed per device.
This value must be between 1 and c_maxLocalUsersPerDeviceCount inclusive.

If a client would violate this limit by calling PartyNetwork::AuthenticateLocalUser(), the operation will fail
asynchronously and PartyAuthenticateLocalUserCompletedStateChange::result will be set to
PartyStateChangeResult::NetworkLimitReached.
maxDevicesPerUserCount uint32_t
The maximum number of devices allowed per user.
This value must be greater than 0.

If a client would violate this limit by calling PartyNetwork::AuthenticateLocalUser(), the operation will fail
asynchronously and PartyAuthenticateLocalUserCompletedStateChange::result will be set to
PartyStateChangeResult::NetworkLimitReached.
maxEndpointsPerDeviceCount uint32_t
The maximum number of endpoints allowed per device.
This value must be between 0 and c_maxNetworkConfigurationMaxEndpointsPerDeviceCount inclusive.

If a client would violate this limit by calling PartyNetwork::CreateEndpoint() after the network configuration was
made available, the call to PartyNetwork::CreateEndpoint() will fail synchronously. If the client had already
queued a violating number of endpoint creations when the network configuration became available, the client
will be kicked from the network and a PartyNetworkDestroyedStateChange will be generated.
directPeerConnectivityOptions PartyDirectPeerConnectivityOptions
Whether and how to support direct peer-to-peer connection attempts among devices in the network.
As part of successfully authenticating an initial user into a network, a device may attempt to establish direct
peer-to-peer connections with other devices already participating in the network when permitted by these flags.
For attempts that are successful, endpoint messages and chat data between the devices will be transmitted
using those direct connections. For attempts that fail due to environmental incompatibilities between the
devices, all communication between those devices will be transmitted via transparent cloud relay servers
instead. If the devices aren't permitted to attempt direct peer connections by these flags, then they never
exchange IP address information and will always transmit endpoint messages and chat data via transparent
cloud relay servers.

You can determine whether the local device actually established a direct peer-to-peer connection to a specific
remote device by calling PartyNetwork::GetDeviceConnectionType().

Successful direct peer connectivity may provide lower latency between some devices, though attempting to
establish it also requires users to disclose their devices' IP addresses to others, which may be a concern for
privacy or for enabling malicious users to potentially attack peers' devices and Internet connections outside of
the title. It also may not be permitted on certain platforms for policy reasons. Be sure to use the appropriate
flags for your performance and security goals.

Besides the specific network's value configured here, the flags may optionally be further constrained by a device
for all networks into which it authenticates by using PartyManager::SetOption() to set
PartyOption::LocalDeviceDirectPeerConnectivityOptionsMask. All flags are evaluated using a bitwise AND
operation. That is, a particular flag is actually only in effect for a given network's pair of devices if it's enabled in
three places: this field for the network, and both devices' respective local mask options. Even if this field permits
direct peer connectivity of the relevant form, either device can unilaterally opt out of the IP address disclosure
and direct connection attempts between them by not enabling the flag in its local device mask option. The
PartyOption::LocalDeviceDirectPeerConnectivityOptionsMask value defaults to permitting all direct peer
connections enabled by networks, so you only need to configure it if you have device-specific requirements to
prevent some or all direct peer connectivity involving it.

To avoid excessive resource consumption, the Party library will also internally prevent any given device from
attempting to establish more than c_maxDirectPeerConnectionsPerDevice direct peer connections across all
networks in which it's currently participating, even if permitted by these flags. This doesn't affect the device's
ability to participate in large or multiple networks with additional remote devices. Communication with
additional devices will simply be transmitted via transparent cloud relay servers.

It's recommended that you don't actively enforce the availability of a direct peer-to-peer connection for any
given pair of devices (i.e., don't call PartyNetwork::LeaveNetwork() if PartyNetwork::GetDeviceConnectionType()
reports a value other than PartyDeviceConnectionType::DirectPeerConnection) since the specific underlying
transmission method in use doesn't alter the overall logical ability to communicate. If your game design has
stringent requirements for maximum message latency that encourage direct peer connectivity, it's better to take
action on the current concrete observations of that latency as reported by the
PartyEndpointStatistic::AverageDeviceRoundTripLatencyInMilliseconds statistic rather than make abstract
assumptions based on transmission mechanism. Otherwise you might continually hinder users trying to play
with the same set of friends who always need to use nearby transparent cloud relay servers due to
environmental factors beyond their control.

Requirements
Header : Party.h

See also
Party members
PartyNetwork::AuthenticateLocalUser
PartyAuthenticateLocalUserCompletedStateChange
PartyManager::ConnectToNetwork
PartyConnectToNetworkCompletedStateChange
PartyNetwork::CreateEndpoint
PartyNetworkDestroyedStateChange
PartyStateChangeResult
PartyDirectPeerConnectivityOptions
PartyNetworkDescriptor
5/24/2022 • 2 minutes to read • Edit Online

A descriptor containing the data required for a device to connect to a network.

Syntax
struct PartyNetworkDescriptor {
char networkIdentifier[c_networkIdentifierStringLength + 1];
char regionName[c_maxRegionNameStringLength + 1];
uint8_t opaqueConnectionInformation[c_opaqueConnectionInformationByteCount];
}

Members
networkIdentifier char[c_networkIdentifierStringLength + 1]
A unique identifier for the network.
This identifier can be used to correlate locally observed PartyNetwork behavior with remote telemetry gathered
by the Party service and transparent cloud relay. It is recommended that this identifier be recorded alongside
any other information the title records to diagnose network behavior.
regionName char[c_maxRegionNameStringLength + 1]
The Azure region in which the network was created.
opaqueConnectionInformation uint8_t[c_opaqueConnectionInformationByteCount]
Connection information for the network used internally by the Party library.

Requirements
Header : Party.h

See also
Party members
PartyProfilingMethodEntranceEventData
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the MethodEntrance type of profiling event.

Syntax
struct PartyProfilingMethodEntranceEventData {
PartyString methodName;
}

Members
methodName PartyString
A string containing the fully qualified name of the method responsible for the callback.

Requirements
Header : Party.h

See also
Party members
PartyProfilingMethodEntranceCallback
PartyProfilingMethodExitEventData
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the MethodExit type of profiling event.

Syntax
struct PartyProfilingMethodExitEventData {
PartyString methodName;
}

Members
methodName PartyString
A string containing the fully qualified name of the method responsible for the callback.

Requirements
Header : Party.h

See also
Party members
PartyProfilingMethodExitCallback
PartyRegion
5/24/2022 • 2 minutes to read • Edit Online

Represents a Party library region.

Syntax
struct PartyRegion {
char regionName[c_maxRegionNameStringLength + 1];
uint32_t roundTripLatencyInMilliseconds;
}

Members
regionName char[c_maxRegionNameStringLength + 1]
The name of the Azure region, such as "eastus2".
This name is not localized to the current user's language, and showing the string directly in UI is not
recommended outside of troubleshooting.
roundTripLatencyInMilliseconds uint32_t
The round trip latency between the local device and the region's datacenter.

Requirements
Header : Party.h

See also
Party members
PartySendMessageQueuingConfiguration
5/24/2022 • 4 minutes to read • Edit Online

Optional configuration parameters for modifying local queuing behavior when sending a message.

Syntax
struct PartySendMessageQueuingConfiguration {
int8_t priority;
uint32_t identityForCancelFilters;
uint32_t timeoutInMilliseconds;
}

Members
priority int8_t
The priority of the locally queued message in relation to chat data or messages sent from other local endpoints.
priority must be a value between c_minSendMessageQueuingPriority and c_maxSendMessageQueuingPriority ,
inclusive. Higher numbers represent higher relative priority (will be transmitted first) over lower numbers. The
default when no PartySendMessageQueuingConfiguration structure is provided to
PartyLocalEndpoint::SendMessage() is c_defaultSendMessageQueuingPriority , which lies exactly in the middle of
the signed integer range (zero).

Send queue priority does not modify the order in which messages sent from a given local endpoint are
transmitted or delivered. It only affects the ordering of messages from different local endpoints, or between an
endpoint and internally transmitted chat data, which uses priority c_chatSendMessageQueuingPriority . The local
endpoint send queue that has the messages with the highest priority value will have its messages eligible for
transmission first. If all remaining messages queued by local endpoints are of equal priority, then the individual
messages will be eligible for transmission in the same order in which their PartyLocalEndpoint::SendMessage()
calls occurred.

One way to think of the behavior is that high priority messages automatically elevate the priority of all previous
messages from the same local endpoint to the same value to ensure timely delivery of the high priority
message but without breaking the sequential delivery expectations of the messages previously transmitted by
the local endpoint. Other local endpoints have their own send sequence, and thus have no such ordering
guarantees (though the Party library makes a best-effort attempt to preserve the ordering in which they were
originally sent where possible).

A message's send queue priority matters when there are more bytes to be sent than the connection can support
due to connection quality or receiver responsiveness. Sending more important messages as higher priority
ensures that they get the first opportunity to use the limited network resources. If you continue to send
messages faster than can successfully be transmitted, lower priority messages may get "starved" and the
associated local endpoint send queue will continue to grow. Be sure to manage such potential growth by
canceling extraneous messages with PartyLocalEndpoint::CancelMessages(), using the timeoutInMilliseconds
field to automatically time out messages that have been queued for too long, or simply reducing the size and/or
frequency of the PartyLocalEndpoint::SendMessage() calls.
identityForCancelFilters uint32_t
A caller-defined value to use when evaluating the message for applicability with cancel filter expressions.
This message identity value can have any caller-specific meaning and is not interpreted by the Party library
other than for use by PartyLocalEndpoint::CancelMessages() when evaluating whether the message matches the
optionally provided cancel filter expression.

A default value of zero is used when no PartySendMessageQueuingConfiguration structure is provided to


PartyLocalEndpoint::SendMessage().

Canceling messages can help prevent the local send queue from growing excessively when experiencing poor
network conditions. Canceling message identities that match certain filter expressions works well when you
have categories of messages that are regularly sent with the latest information and should replace any
previously queued out-of-date message that might still be awaiting a transmission opportunity. Canceling can
also be useful when you have an instance or category of opportunistic messages whose loss would not be fatal
and that aren't worth the bandwidth to try transmitting instead of more valuable queued messages.

This local identity value is not part of the transmitted data payload. It has no applicability once the message
begins transmitting and can no longer be removed from the local send queue by
PartyLocalEndpoint::CancelMessages().
timeoutInMilliseconds uint32_t
The maximum time, in milliseconds, that the message is permitted to remain in a Party-managed send queue
awaiting a transmission opportunity.
If the message has not started transmitting when this timeout elapses due to connection quality or receiver
responsiveness, the message will be aborted and removed from the queue without being sent.

A timeoutInMilliseconds value of zero indicates that there should be no timeout and that the message should
remain queued until it is either successfully transmitted, is explicitly canceled, or encounters some transmission
failure such as remote disconnection. Zero is the default when no PartySendMessageQueuingConfiguration
structure is provided to PartyLocalEndpoint::SendMessage().

Message send queue timeouts can help prevent send queues from growing excessively when experiencing poor
network conditions. They work well with messages that contain time-sensitive, periodic data where it would be a
waste of bandwidth to transmit ones that are stale because a newer complete replacement message is sent
regularly, and the loss of any individual one is not fatal.

This timeout value only affects Party-managed send queuing. It does not affect the time it takes to actually
transmit a message (environmental latency) nor alter how long to wait for the receiver to acknowledge the
transmission if applicable.

This timeout value is evaluated twice when sending to targets without direct peer connections: once for the
sending client's local send queues to the transparent cloud relay, affected by local environmental conditions and
transmission rates to the relay, and a second time on the relay itself, which may be forced to queue messages
before forwarding based on differing network conditions, transmission rates, or responsiveness of the remote
targets.

Requirements
Header : Party.h

See also
Party members
PartyLocalEndpoint::SendMessage
PartyTranslation
5/24/2022 • 2 minutes to read • Edit Online

A translation.

Syntax
struct PartyTranslation {
PartyStateChangeResult result;
PartyError errorDetail;
PartyString languageCode;
PartyTranslationReceivedOptions options;
PartyString translation;
}

Members
result PartyStateChangeResult

Indicates whether the translation operation succeeded.


On success, translation will be a string of non-zero length containing the translated text. On failure, the string
will be empty.
errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
The human-readable form of this error detail can be retrieved via PartyManager::GetErrorMessage().
languageCode PartyString
The language code of the translation.
The language code will be in BCP 47 format, such as en-US for English (United States). Supported language
codes are enumerated at https://docs.microsoft.com/azure/cognitive-services/speech-service/language-
support.
options PartyTranslationReceivedOptions
Additional options describing the translation.
translation PartyString
The translation string.
By default, profanity masking is enabled and replaces each character of a profane word with an asterisk.
Profanity masking is applied after translating the unmasked source transcription. Depending on context, it's
possible for the transcription to contain masked profanity but not the translation. Similarly, it's possible for the
translation to contain masked profanity but not the original transcription. Profanity masking can be disabled via
PartyVoiceChatTranscriptionOptions::DisableProfanityMasking.

The translation string may be up to c_maxChatTextMessageLength characters long, not including the null
terminator. Truncation occurs if the translated string length would exceed that limit, which can happen due to
language differences even though the original string length is less than or equal to c_maxChatTextMessageLength .
In such a case, options will contain PartyTranslationReceivedOptions::Truncated. Truncation may occur at an
arbitrary point in the UTF-8 byte sequence and may not result in a complete, valid character or word. Strings are
always null terminated, even when truncated.

Requirements
Header : Party.h

See also
Party members
PartyAuthenticateLocalUserCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the AuthenticateLocalUserCompleted type of state change.

Syntax
struct PartyAuthenticateLocalUserCompletedStateChange : PartyStateChange {
PartyStateChangeResult result;
PartyError errorDetail;
PartyNetwork* network;
PartyLocalUser* localUser;
PartyString invitationIdentifier;
void* asyncIdentifier;
}

Members
result PartyStateChangeResult

Indicates that the authenticate local user operation Succeeded or provides the reason that it failed.
errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
The human-readable form of this error detail can be retrieved via PartyManager::GetErrorMessage().
network PartyNetwork*
The network used in the call associated with this state change.
localUser PartyLocalUser*
The local user provided to the call associated with this state change.
invitationIdentifier PartyString
The identifier of the invitation used to authenticate into the network.
asyncIdentifier void*
The async identifier provided to the call associated with this state change.

Requirements
Header : Party.h

See also
Party members
PartyNetwork::AuthenticateLocalUser
PartyChatControlCreatedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the ChatControlCreated type of state change.

Syntax
struct PartyChatControlCreatedStateChange : PartyStateChange {
PartyChatControl* chatControl;
}

Members
chatControl PartyChatControl*
The chat control that was created.

Requirements
Header : Party.h

See also
Party members
PartyLocalDevice::CreateChatControl
PartyChatControlDestroyedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the ChatControlDestroyed type of state change.

Syntax
struct PartyChatControlDestroyedStateChange : PartyStateChange {
PartyChatControl* chatControl;
PartyDestroyedReason reason;
PartyError errorDetail;
}

Members
chatControl PartyChatControl*
The chat control that was destroyed.
The memory remains valid until this state change is returned.
reason PartyDestroyedReason
The reason the chat control was destroyed.
errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
The human-readable form of this error detail can be retrieved via PartyManager::GetErrorMessage().

Requirements
Header : Party.h

See also
Party members
PartyLocalDevice::DestroyChatControl
PartyChatControlJoinedNetworkStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the ChatControlJoinedNetwork type of state change.

Syntax
struct PartyChatControlJoinedNetworkStateChange : PartyStateChange {
PartyNetwork* network;
PartyChatControl* chatControl;
}

Members
network PartyNetwork*
The network joined.
chatControl PartyChatControl*
The chat control that joined the network.

Requirements
Header : Party.h

See also
Party members
PartyNetwork::ConnectChatControl
PartyChatControlLeftNetworkStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the ChatControlLeftNetwork type of state change.

Syntax
struct PartyChatControlLeftNetworkStateChange : PartyStateChange {
PartyDestroyedReason reason;
PartyError errorDetail;
PartyNetwork* network;
PartyChatControl* chatControl;
}

Members
reason PartyDestroyedReason

The reason the chat control left the network.


errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
The human-readable form of this error detail can be retrieved via PartyManager::GetErrorMessage().
network PartyNetwork*
The network left.
chatControl PartyChatControl*
The chat control that left the network.

Requirements
Header : Party.h

See also
Party members
PartyNetwork::DisconnectChatControl
PartyChatTextReceivedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the ChatTextReceived type of state change.

Syntax
struct PartyChatTextReceivedStateChange : PartyStateChange {
PartyChatControl* senderChatControl;
uint32_t receiverChatControlCount;
PartyLocalChatControlArray receiverChatControls;
PartyString languageCode;
PartyString chatText;
uint32_t dataSize;
const void* data;
uint32_t translationCount;
PartyTranslation* translations;
PartyChatTextReceivedOptions options;
PartyString originalChatText;
PartyError errorDetail;
}

Members
senderChatControl PartyChatControl*
The chat control object that originated the text message.
receiverChatControlCount uint32_t
The number of local receiver chat controls to which the text message is addressed.
receiverChatControls PartyLocalChatControlArray
array of size receiverChatControlCount

The local receiver chat controls to which the text message is addressed.
languageCode PartyString
The language of the chat text.
The language will only be provided when translation to the local language is enabled. If translation isn't enabled,
or failure is encountered during translation, the language code will be an empty string.

The language code will be in BCP 47 format, such as en-US for English (United States). Supported language
codes are enumerated at https://docs.microsoft.com/azure/cognitive-services/speech-service/language-
support.
chatText PartyString
The received chat text.
The string may be up to c_maxChatTextMessageLength characters long, not including the null terminator.

When filtering is enabled, this text may not be the exact text sent by the remote user. The exact source text can be
retrieved from the originalChatText field.
dataSize uint32_t
The size of the data associated with this text message.
data const void*
buffer of size dataSize bytes
The data associated with this text message.
translationCount uint32_t
The number of translations associated with the chat text.
Translations will be provided if PartyTextChatOptions::TranslateToLocalLanguage had previously been specified
via PartyLocalChatControl::SetTextChatOptions() on a chat control local to this device. There may be more than
one translation if multiple local chat controls have enabled translation and the local chat controls have specified
different languages via PartyLocalDevice::CreateChatControl(). In that case, the app can compare the
languageCode field of each PartyTranslation in translations against the language code, obtained via
PartyLocalChatControl::GetLanguage(), for each local chat control in receiverChatControls to determine the
target local chat control for each translation.
translations PartyTranslation*
array of size translationCount

An array containing the translations of the chat text string.


Translations will be provided if PartyTextChatOptions::TranslateToLocalLanguage had previously been specified
via PartyLocalChatControl::SetTextChatOptions() on a chat control local to this device. There may be more than
one translation if multiple local chat controls have enabled translation and the local chat controls have specified
different languages via PartyLocalDevice::CreateChatControl(). In that case, the app can compare the
languageCode field of each PartyTranslation in translations against the language code, obtained via
PartyLocalChatControl::GetLanguage(), for each local chat control in receiverChatControls to determine the
target local chat control for each translation.
options PartyChatTextReceivedOptions
Flags describing additional information about the chat text.
originalChatText PartyString
The original version of the incoming text chat.
This field is always the unfiltered source text sent by the remote user. If filtering isn't enabled, it's a pointer to
chatText . If filtering is enabled but filtering was not needed, as indicated by
PartyChatTextReceivedOptions::None in the options field, then this is a pointer to chatText .
errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
This error is intended for diagnostic purposes only. If an error occurs, the
PartyChatTextReceivedOptions::FilteredDueToError flag will be present in the options field.

Requirements
Header : Party.h

See also
Party members
PartyLocalDevice::CreateChatControl
PartyLocalChatControl::SendText
PartyLocalChatControl::SetTextChatOptions
PartyConfigureAudioManipulationCaptureStreamCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the ConfigureAudioManipulationCaptureStreamCompleted type of state change.

Syntax
struct PartyConfigureAudioManipulationCaptureStreamCompletedStateChange : PartyStateChange {
PartyStateChangeResult result;
PartyError errorDetail;
PartyLocalChatControl* localChatControl;
PartyAudioManipulationSinkStreamConfiguration* configuration;
void* asyncIdentifier;
}

Members
result PartyStateChangeResult

Indicates that the operation Succeeded or the reason that it failed.


On success, the sink stream provided by PartyLocalChatControl::GetAudioManipulationCaptureStream() will be
updated.
errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
The human-readable form of this error detail can be retrieved via PartyManager::GetErrorMessage().
localChatControl PartyLocalChatControl*
The chat control used in to the call associated with this state change.
configuration PartyAudioManipulationSinkStreamConfiguration*
The configuration provided to the call associated with this state change.
asyncIdentifier void*
The async identifier provided to the call associated with this state change.

Requirements
Header : Party.h

See also
Party members
PartyLocalChatControl::ConfigureAudioManipulationCaptureStream
PartyConfigureAudioManipulationRenderStreamCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the ConfigureAudioManipulationRenderStreamCompleted type of state change.

Syntax
struct PartyConfigureAudioManipulationRenderStreamCompletedStateChange : PartyStateChange {
PartyStateChangeResult result;
PartyError errorDetail;
PartyLocalChatControl* localChatControl;
PartyAudioManipulationSinkStreamConfiguration* configuration;
void* asyncIdentifier;
}

Members
result PartyStateChangeResult

Indicates that the operation Succeeded or the reason that it failed.


On success, the sink stream provided by PartyLocalChatControl::GetAudioManipulationRenderStream() will be
updated.
errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
The human-readable form of this error detail can be retrieved via PartyManager::GetErrorMessage().
localChatControl PartyLocalChatControl*
The chat control used in the call associated with this state change.
configuration PartyAudioManipulationSinkStreamConfiguration*
The configuration provided to the call associated with this state change.
asyncIdentifier void*
The async identifier provided to the call associated with this state change.

Requirements
Header : Party.h

See also
Party members
PartyLocalChatControl::ConfigureAudioManipulationRenderStream
PartyConfigureAudioManipulationVoiceStreamCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the ConfigureAudioManipulationVoiceStreamCompleted type of state change.

Syntax
struct PartyConfigureAudioManipulationVoiceStreamCompletedStateChange : PartyStateChange {
PartyStateChangeResult result;
PartyError errorDetail;
PartyChatControl* chatControl;
PartyAudioManipulationSourceStreamConfiguration* configuration;
void* asyncIdentifier;
}

Members
result PartyStateChangeResult

Indicates that the operation Succeeded or the reason that it failed.


On success, the source stream provided by PartyChatControl::GetAudioManipulationVoiceStream() will be
updated.
errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
The human-readable form of this error detail can be retrieved via PartyManager::GetErrorMessage().
chatControl PartyChatControl*
The chat control used in the call associated with this state change.
configuration PartyAudioManipulationSourceStreamConfiguration*
The configuration provided to the call associated with this state change.
asyncIdentifier void*
The async identifier provided to the call associated with this state change.

Requirements
Header : Party.h

See also
Party members
PartyChatControl::ConfigureAudioManipulationVoiceStream
PartyConnectChatControlCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the ConnectChatControlCompleted type of state change.

Syntax
struct PartyConnectChatControlCompletedStateChange : PartyStateChange {
PartyStateChangeResult result;
PartyError errorDetail;
PartyNetwork* network;
PartyLocalChatControl* localChatControl;
void* asyncIdentifier;
}

Members
result PartyStateChangeResult

Indicates that the operation Succeeded or the reason that it failed.


errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
The human-readable form of this error detail can be retrieved via PartyManager::GetErrorMessage().
network PartyNetwork*
The network used in the call associated with this state change.
localChatControl PartyLocalChatControl*
The chat control provided to the call associated with this state change.
asyncIdentifier void*
The async identifier provided to the call associated with this state change.

Requirements
Header : Party.h

See also
Party members
PartyNetwork::ConnectChatControl
PartyConnectToNetworkCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the ConnectToNetworkCompleted type of state change.

Syntax
struct PartyConnectToNetworkCompletedStateChange : PartyStateChange {
PartyStateChangeResult result;
PartyError errorDetail;
PartyNetworkDescriptor networkDescriptor;
void* asyncIdentifier;
PartyNetwork* network;
}

Members
result PartyStateChangeResult

Indicates that the connect to network operation Succeeded or provides the reason that it failed.
errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
The human-readable form of this error detail can be retrieved via PartyManager::GetErrorMessage().
networkDescriptor PartyNetworkDescriptor
The network descriptor provided to the call associated with this state change.
asyncIdentifier void*
The async identifier provided to the call associated with this state change.
network PartyNetwork*
The network that was connected to.

Requirements
Header : Party.h

See also
Party members
PartyManager::ConnectToNetwork
PartyCreateChatControlCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the CreateChatControlCompleted type of state change.

Syntax
struct PartyCreateChatControlCompletedStateChange : PartyStateChange {
PartyStateChangeResult result;
PartyError errorDetail;
PartyLocalDevice* localDevice;
PartyLocalUser* localUser;
PartyString languageCode;
void* asyncIdentifier;
PartyLocalChatControl* localChatControl;
}

Members
result PartyStateChangeResult

Indicates that the chat control creation operation Succeeded or provides the reason that it failed.
errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
The human-readable form of this error detail can be retrieved via PartyManager::GetErrorMessage().
localDevice PartyLocalDevice*
The local device used in the call associated with this state change.
localUser PartyLocalUser*
The local user provided to the call associated with this state change.
languageCode PartyString
The language code provided to the call associated with this state change.
asyncIdentifier void*
The async identifier provided to the call associated with this state change.
localChatControl PartyLocalChatControl*
The chat control that was created.

Requirements
Header : Party.h

See also
Party members
PartyLocalDevice::CreateChatControl
PartyCreateEndpointCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the CreateEndpointCompleted type of state change.

Syntax
struct PartyCreateEndpointCompletedStateChange : PartyStateChange {
PartyStateChangeResult result;
PartyError errorDetail;
PartyNetwork* network;
PartyLocalUser* localUser;
void* asyncIdentifier;
PartyLocalEndpoint* localEndpoint;
}

Members
result PartyStateChangeResult

Indicates that the create endpoint Succeeded or provides the reason that it failed.
errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
The human-readable form of this error detail can be retrieved via PartyManager::GetErrorMessage().
network PartyNetwork*
The network used in the call associated with this state change.
localUser PartyLocalUser*
may be nullptr
The local user provided to the call associated with this state change if one was provided.
asyncIdentifier void*
The async identifier provided to the call associated with this state change.
localEndpoint PartyLocalEndpoint*
The endpoint that was created.

Remarks
An associated PartyEndpointCreatedStateChange will be generated before this state change is generated.

Requirements
Header : Party.h

See also
Party members
PartyNetwork::CreateEndpoint
PartyCreateInvitationCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the CreateInvitationCompleted type of state change.

Syntax
struct PartyCreateInvitationCompletedStateChange : PartyStateChange {
PartyStateChangeResult result;
PartyError errorDetail;
PartyNetwork* network;
PartyLocalUser* localUser;
void* asyncIdentifier;
PartyInvitation* invitation;
}

Members
result PartyStateChangeResult

Indicates that the PartyNetwork::CreateInvitation() operation succeeded or provides the reason that it failed.
errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
The human-readable form of this error detail can be retrieved via PartyManager::GetErrorMessage().
network PartyNetwork*
The network used in the call associated with this state change.
localUser PartyLocalUser*
The local user that created the invitation.
asyncIdentifier void*
The async identifier provided to the call associated with this state change.
invitation PartyInvitation*
The invitation created for the network.

Requirements
Header : Party.h

See also
Party members
PartyNetwork::CreateInvitation
PartyCreateNewNetworkCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the CreateNewNetworkCompleted type of state change.

Syntax
struct PartyCreateNewNetworkCompletedStateChange : PartyStateChange {
PartyStateChangeResult result;
PartyError errorDetail;
PartyLocalUser* localUser;
PartyNetworkConfiguration networkConfiguration;
uint32_t regionCount;
const PartyRegion* regions;
void* asyncIdentifier;
PartyNetworkDescriptor networkDescriptor;
PartyString appliedInitialInvitationIdentifier;
}

Members
result PartyStateChangeResult

Indicates that the create new network operation Succeeded or provides the reason that it failed.
errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
The human-readable form of this error detail can be retrieved via PartyManager::GetErrorMessage().
localUser PartyLocalUser*
The local user provided to the call associated with this state change.
networkConfiguration PartyNetworkConfiguration
The network configuration provided to the call associated with this state change.
regionCount uint32_t
The number of regions provided to the call associated with this state change.
regions const PartyRegion*
The regions provided to the call associated with this state change.
asyncIdentifier void*
The async identifier provided to the call associated with this state change.
networkDescriptor PartyNetworkDescriptor
The network descriptor of the network that was created.
The regionName and opaqueConnectionInformation fields are only populated if the result field is
PartyStateChangeResult::Succeeded. The networkIdentifier field should always be populated. If the result field is
PartyStateChangeResult::Succeeded, this network descriptor is serializable via
PartyManager::SerializeNetworkDescriptor().
appliedInitialInvitationIdentifier PartyString
The identifier for the network's initial invitation.

Requirements
Header : Party.h

See also
Party members
PartyManager::CreateNewNetwork
PartyManager::SerializeNetworkDescriptor
PartyDataBuffersReturnedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the DataBuffersReturned type of state change.

Syntax
struct PartyDataBuffersReturnedStateChange : PartyStateChange {
PartyNetwork* network;
PartyLocalEndpoint* localSenderEndpoint;
uint32_t dataBufferCount;
const PartyDataBuffer* dataBuffers;
void* messageIdentifier;
}

Members
network PartyNetwork*
The network on which the message was sent.
localSenderEndpoint PartyLocalEndpoint*
The local endpoint used to send the message.
dataBufferCount uint32_t
The number of data buffers.
dataBuffers const PartyDataBuffer*
array of size dataBufferCount

The data buffers.


messageIdentifier void*
The message identifier provided to the call associated with this state change.

Remarks
This state change is only returned if the corresponding call to PartyLocalEndpoint::SendMessage() included the
PartySendMessageOptions::DontCopyDataBuffers option. This state change is returned once the data buffers
passed with this call are no longer in use by the library.

Requirements
Header : Party.h

See also
Party members
PartyLocalEndpoint::SendMessage
PartyDestroyChatControlCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the DestroyChatControlCompleted type of state change.

Syntax
struct PartyDestroyChatControlCompletedStateChange : PartyStateChange {
PartyStateChangeResult result;
PartyError errorDetail;
PartyLocalDevice* localDevice;
PartyLocalChatControl* localChatControl;
void* asyncIdentifier;
}

Members
result PartyStateChangeResult

Indicates that the chat control destruction operation Succeeded or provides the reason that it failed.
errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
The human-readable form of this error detail can be retrieved via PartyManager::GetErrorMessage().
localDevice PartyLocalDevice*
The local device used in the call associated with this state change.
localChatControl PartyLocalChatControl*
The chat control that was destroyed.
The memory remains valid until this state change is returned.
asyncIdentifier void*
The async identifier provided to the call associated with this state change.

Requirements
Header : Party.h

See also
Party members
PartyLocalDevice::DestroyChatControl
PartyDestroyEndpointCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the DestroyEndpointCompleted type of state change.

Syntax
struct PartyDestroyEndpointCompletedStateChange : PartyStateChange {
PartyStateChangeResult result;
PartyError errorDetail;
PartyNetwork* network;
PartyLocalEndpoint* localEndpoint;
void* asyncIdentifier;
}

Members
result PartyStateChangeResult

Indicates that the destroy endpoint operation Succeeded or provides the reason that it failed.
errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
The human-readable form of this error detail can be retrieved via PartyManager::GetErrorMessage().
network PartyNetwork*
The network used in the call associated with this state change.
localEndpoint PartyLocalEndpoint*
The endpoint provided to the call associated with this state change.
asyncIdentifier void*
The async identifier provided to the call associated with this state change.

Remarks
An associated PartyEndpointDestroyedStateChange will be generated before this state change is generated.

Requirements
Header : Party.h

See also
Party members
PartyNetwork::DestroyEndpoint
PartyDestroyLocalUserCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the DestroyLocalUserCompleted type of state change.

Syntax
struct PartyDestroyLocalUserCompletedStateChange : PartyStateChange {
PartyStateChangeResult result;
PartyError errorDetail;
PartyLocalUser* localUser;
void* asyncIdentifier;
}

Members
result PartyStateChangeResult

Indicates that the destroy local user operation Succeeded or provides the reason that it failed.
errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
The human-readable form of this error detail can be retrieved via PartyManager::GetErrorMessage().
localUser PartyLocalUser*
The local user provided to the call associated with this state change.
asyncIdentifier void*
The async identifier provided to the call associated with this state change.

Remarks
This PartyLocalUser will be removed from all dependent networks prior to this state change. All dependent
PartyEndpoint and PartyChatControl objects will be destroyed with reason
PartyDestroyedReason::UserRemoved prior to the PartyLocalUser being removed from its dependent networks.
Once this state change is returned to PartyManager::FinishProcessingStateChanges(), the PartyLocalUser object
memory will become invalid.

Requirements
Header : Party.h

See also
Party members
PartyManager::DestroyLocalUser
PartyDisconnectChatControlCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the DisconnectChatControlCompleted type of state change.

Syntax
struct PartyDisconnectChatControlCompletedStateChange : PartyStateChange {
PartyStateChangeResult result;
PartyError errorDetail;
PartyNetwork* network;
PartyLocalChatControl* localChatControl;
void* asyncIdentifier;
}

Members
result PartyStateChangeResult

Indicates that the operation Succeeded or the reason that it failed.


errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
The human-readable form of this error detail can be retrieved via PartyManager::GetErrorMessage().
network PartyNetwork*
The network used in the call associated with this state change.
localChatControl PartyLocalChatControl*
The chat control provided to the call associated with this state change.
asyncIdentifier void*
The async identifier provided to the call associated with this state change.

Requirements
Header : Party.h

See also
Party members
PartyNetwork::DisconnectChatControl
PartyEndpointCreatedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the EndpointCreated type of state change.

Syntax
struct PartyEndpointCreatedStateChange : PartyStateChange {
PartyNetwork* network;
PartyEndpoint* endpoint;
}

Members
network PartyNetwork*
The network of the endpoint that was created.
endpoint PartyEndpoint*
The endpoint that was created.

Requirements
Header : Party.h

See also
Party members
PartyEndpointDestroyedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the EndpointDestroyed type of state change.

Syntax
struct PartyEndpointDestroyedStateChange : PartyStateChange {
PartyNetwork* network;
PartyEndpoint* endpoint;
PartyDestroyedReason reason;
PartyError errorDetail;
}

Members
network PartyNetwork*
The network of the endpoint that was destroyed.
endpoint PartyEndpoint*
The endpoint that was destroyed.
reason PartyDestroyedReason
The reason the endpoint was destroyed.
errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
The human-readable form of this error detail can be retrieved via PartyManager::GetErrorMessage().

Requirements
Header : Party.h

See also
Party members
PartyEndpointMessageReceivedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the EndpointMessageReceived type of state change.

Syntax
struct PartyEndpointMessageReceivedStateChange : PartyStateChange {
PartyNetwork* network;
PartyEndpoint* senderEndpoint;
uint32_t receiverEndpointCount;
PartyLocalEndpointArray receiverEndpoints;
PartyMessageReceivedOptions options;
uint32_t messageSize;
const void* messageBuffer;
}

Members
network PartyNetwork*
The network containing the endpoint on which the message was received.
senderEndpoint PartyEndpoint*
The endpoint which sent the message.
receiverEndpointCount uint32_t
The number of local endpoints to which the message was sent. This value will always be greater than zero. If the
sender specified an empty target endpoints array in the PartyLocalEndpoint::SendMessage() call that resulted in
this state change, receiverEndpointCount and receiverEndpoints will contain all local endpoints.
receiverEndpoints PartyLocalEndpointArray
array of size receiverEndpointCount

The local endpoints to which the message was sent. This array will never be empty. If the sender specified an
empty target endpoints array in the PartyLocalEndpoint::SendMessage() call that resulted in this state change,
receiverEndpointCount and receiverEndpoints will contain all local endpoints.

options PartyMessageReceivedOptions
The options used to send the message.
messageSize uint32_t
The size of the message in bytes.
messageBuffer const void*
buffer of size messageSize bytes
The message buffer.

Requirements
Header : Party.h
See also
Party members
PartyLocalEndpoint::SendMessage
PartyInvitationCreatedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the InvitationCreated type of state change.

Syntax
struct PartyInvitationCreatedStateChange : PartyStateChange {
PartyNetwork* network;
PartyInvitation* invitation;
}

Members
network PartyNetwork*
The network of the invitation that was created.
invitation PartyInvitation*
The invitation that was created.
Upon receiving this state change, the invitation object will be queryable via PartyNetwork::GetInvitations().

Requirements
Header : Party.h

See also
Party members
PartyInvitationDestroyedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the InvitationDestroyed type of state change.

Syntax
struct PartyInvitationDestroyedStateChange : PartyStateChange {
PartyNetwork* network;
PartyInvitation* invitation;
PartyDestroyedReason reason;
PartyError errorDetail;
}

Members
network PartyNetwork*
The network of the invitation that was destroyed.
invitation PartyInvitation*
The invitation that was destroyed.
Upon receiving this state change, the invitation object will no longer be queryable via
PartyNetwork::GetInvitations().
reason PartyDestroyedReason
The reason the invitation was destroyed.
If the invitation object was destroyed because it was explicitly revoked via PartyNetwork::RevokeInvitation() or
automatically revoked when the creating local user left the network, this value will be
PartyDestroyedReason::Requested. If the invitation object was destroyed because the local client is no longer
authenticated in the network, this value will be PartyDestroyedReason::DeviceLostAuthentication.
errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
The human-readable form of this error detail can be retrieved via PartyManager::GetErrorMessage().

Requirements
Header : Party.h

See also
Party members
PartyLeaveNetworkCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the LeaveNetworkCompleted type of state change.

Syntax
struct PartyLeaveNetworkCompletedStateChange : PartyStateChange {
PartyStateChangeResult result;
PartyError errorDetail;
PartyNetwork* network;
void* asyncIdentifier;
}

Members
result PartyStateChangeResult

Indicates that the leave network operation Succeeded or provides the reason that it failed.
errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
The human-readable form of this error detail can be retrieved via PartyManager::GetErrorMessage().
network PartyNetwork*
The network used in call associated with this state change.
asyncIdentifier void*
The async identifier provided to the call associated with this state change.

Remarks
An associated PartyNetworkDestroyedStateChange will be generated before this state change is generated. The
network object network is only valid until this state change is returned to
PartyManager::FinishProcessingStateChanges().

Requirements
Header : Party.h

See also
Party members
PartyNetwork::LeaveNetwork
PartyLocalChatAudioInputChangedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the LocalChatAudioInputChanged type of state change.

Syntax
struct PartyLocalChatAudioInputChangedStateChange : PartyStateChange {
PartyLocalChatControl* localChatControl;
PartyAudioInputState state;
PartyError errorDetail;
}

Members
localChatControl PartyLocalChatControl*
The local chat control which had an audio input state change.
state PartyAudioInputState
Indicates the new state of the audio input associated with the chat control.
errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
The human-readable form of this error detail can be retrieved via PartyManager::GetErrorMessage().

Requirements
Header : Party.h

See also
Party members
PartyLocalChatControl::SetAudioInput
PartyLocalChatAudioOutputChangedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the LocalChatAudioOutputChanged type of state change.

Syntax
struct PartyLocalChatAudioOutputChangedStateChange : PartyStateChange {
PartyLocalChatControl* localChatControl;
PartyAudioOutputState state;
PartyError errorDetail;
}

Members
localChatControl PartyLocalChatControl*
The local chat control which had an audio output state change.
state PartyAudioOutputState
Indicates the new state of the audio output associated with the chat control.
errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
The human-readable form of this error detail can be retrieved via PartyManager::GetErrorMessage().

Requirements
Header : Party.h

See also
Party members
PartyLocalChatControl::SetAudioOutput
PartyLocalUserRemovedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the LocalUserRemoved type of state change.

Syntax
struct PartyLocalUserRemovedStateChange : PartyStateChange {
PartyNetwork* network;
PartyLocalUser* localUser;
PartyLocalUserRemovedReason removedReason;
}

Members
network PartyNetwork*
The network that the local user was removed from.
localUser PartyLocalUser*
The local user provided to the call associated with this state change.
removedReason PartyLocalUserRemovedReason
The reason the user was removed from the network.

Remarks
All PartyEndpoints depending on this user will have been destroyed prior to this state change being generated.
All PartyChatControls depending on this user will have left the network prior to this state change being
generated.

Requirements
Header : Party.h

See also
Party members
PartyNetwork::RemoveLocalUser
PartyManager::DestroyLocalUser
PartyNetworkConfigurationMadeAvailableStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the NetworkConfigurationMadeAvailable type of state change.

Syntax
struct PartyNetworkConfigurationMadeAvailableStateChange : PartyStateChange {
PartyNetwork* network;
PartyNetworkConfiguration* networkConfiguration;
}

Members
network PartyNetwork*
The network where the network configuration was made available.
networkConfiguration PartyNetworkConfiguration*
The newly available network configuration.

Requirements
Header : Party.h

See also
Party members
PartyNetwork::GetNetworkConfiguration
PartyNetworkDescriptorChangedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the NetworkDescriptorChanged type of state change.

Syntax
struct PartyNetworkDescriptorChangedStateChange : PartyStateChange {
PartyNetwork* network;
}

Members
network PartyNetwork*
The network where the network descriptor changed.

Remarks
This state change is generated when the network descriptor of a network changes due to migration from one
server to another. Use PartyNetwork::GetNetworkDescriptor() to get the new network descriptor. The old
network descriptor is no longer guaranteed to be usable for connecting to the network, so any outstanding
external references to the old network descriptor (such as invitations sent over a social network) should be
updated.

Requirements
Header : Party.h

See also
Party members
PartyNetwork::GetNetworkDescriptor
PartyNetworkDestroyedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the NetworkDestroyed type of state change.

Syntax
struct PartyNetworkDestroyedStateChange : PartyStateChange {
PartyDestroyedReason reason;
PartyError errorDetail;
PartyNetwork* network;
}

Members
reason PartyDestroyedReason

Indicates why the network was destroyed.


errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
The human-readable form of this error detail can be retrieved via PartyManager::GetErrorMessage().
network PartyNetwork*
The network that was destroyed.

Requirements
Header : Party.h

See also
Party members
PartyPopulateAvailableTextToSpeechProfilesCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the PopulateAvailableTextToSpeechProfilesCompleted type of state change.

Syntax
struct PartyPopulateAvailableTextToSpeechProfilesCompletedStateChange : PartyStateChange {
PartyStateChangeResult result;
PartyError errorDetail;
PartyLocalChatControl* localChatControl;
void* asyncIdentifier;
}

Members
result PartyStateChangeResult

Indicates that the operation Succeeded or the reason that it failed.


On success, the profile list provided by PartyLocalChatControl::GetAvailableTextToSpeechProfiles() will be
populated with the results of the operation. On failure, the profile list will remain unchanged.
errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
The human-readable form of this error detail can be retrieved via PartyManager::GetErrorMessage().
localChatControl PartyLocalChatControl*
The chat control provided to the call associated with this state change.
asyncIdentifier void*
The async identifier provided to the call associated with this state change.

Requirements
Header : Party.h

See also
Party members
PartyLocalChatControl::PopulateAvailableTextToSpeechProfiles
PartyRegionsChangedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the RegionsChanged type of state change.

Syntax
struct PartyRegionsChangedStateChange : PartyStateChange {
PartyStateChangeResult result;
PartyError errorDetail;
}

Members
result PartyStateChangeResult

Indicates whether a background operation to query the list of supported regions and the latency to each region
Succeeded, or provides the reason that it failed.
On success, the region list provided by PartyManager::GetRegions() will be populated with the results of the
operation. On failure, the region list provided by PartyManager::GetRegions() will be empty.

If the result is PartyStateChangeResult::FailedToBindToLocalUdpSocket, the library couldn't bind to the local UDP
socket specified in the PartyOption::LocalUdpSocketBindAddress option. The title must clean up its instance of
the library, update the PartyOption::LocalUdpSocketBindAddress option to a valid, available bind address, and
re-initialize the library.
errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
The human-readable form of this error detail can be retrieved via PartyManager::GetErrorMessage().

Requirements
Header : Party.h

See also
Party members
PartyManager::GetRegions
PartyRemoteDeviceCreatedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the RemoteDeviceCreated type of state change.

Syntax
struct PartyRemoteDeviceCreatedStateChange : PartyStateChange {
PartyDevice* device;
}

Members
device PartyDevice*

The device that was created.

Remarks
This state change indicates that the device was just created.

Requirements
Header : Party.h

See also
Party members
PartyRemoteDeviceDestroyedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the RemoteDeviceDestroyed type of state change.

Syntax
struct PartyRemoteDeviceDestroyedStateChange : PartyStateChange {
PartyDevice* device;
}

Members
device PartyDevice*

The device that was destroyed.

Remarks
This state change is generated when device has left all networks.

Requirements
Header : Party.h

See also
Party members
PartyRemoteDeviceJoinedNetworkStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the RemoteDeviceJoinedNetwork type of state change.

Syntax
struct PartyRemoteDeviceJoinedNetworkStateChange : PartyStateChange {
PartyDevice* device;
PartyNetwork* network;
}

Members
device PartyDevice*

The device that joined.


network PartyNetwork*
The network that was joined.

Remarks
This state change indicates that the device has just joined the network.

Requirements
Header : Party.h

See also
Party members
PartyRemoteDeviceLeftNetworkStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the RemoteDeviceLeftNetwork type of state change.

Syntax
struct PartyRemoteDeviceLeftNetworkStateChange : PartyStateChange {
PartyDestroyedReason reason;
PartyError errorDetail;
PartyDevice* device;
PartyNetwork* network;
}

Members
reason PartyDestroyedReason

The reason the device left the network.


errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
The human-readable form of this error detail can be retrieved via PartyManager::GetErrorMessage().
device PartyDevice*
The device that left.
network PartyNetwork*
The network that was left.

Remarks
This state change indicates that the device just left the network.

Requirements
Header : Party.h

See also
Party members
PartyRemoveLocalUserCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the RemoveLocalUserCompleted type of state change.

Syntax
struct PartyRemoveLocalUserCompletedStateChange : PartyStateChange {
PartyStateChangeResult result;
PartyError errorDetail;
PartyNetwork* network;
PartyLocalUser* localUser;
void* asyncIdentifier;
}

Members
result PartyStateChangeResult

Indicates that the remove local user operation Succeeded or provides the reason that it failed.
errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
The human-readable form of this error detail can be retrieved via PartyManager::GetErrorMessage().
network PartyNetwork*
The network used in the call associated with this state change.
localUser PartyLocalUser*
The local user provided to the call associated with this state change.
asyncIdentifier void*
The async identifier provided to the call associated with this state change.

Remarks
All PartyEndpoints and PartyChatControls depending upon this user will have been destroyed with reason
PartyDestroyedReason::UserRemoved before this state change is generated. If the user referenced by this state
change was the last authenticated user in the network, then all remaining PartyEndpoints on this device, which
at this point inherently consists of only endpoints associated with the last user or no user, will also have been
destroyed before this state change is generated. An associated PartyLocalUserRemovedStateChange will have
been generated before this state change is generated.

Requirements
Header : Party.h

See also
Party members
PartyChatControlDestroyedStateChange
PartyChatControlLeftNetworkStateChange
PartyEndpointDestroyedStateChange
PartyNetwork::RemoveLocalUser
PartyRevokeInvitationCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the RevokeInvitationCompleted type of state change.

Syntax
struct PartyRevokeInvitationCompletedStateChange : PartyStateChange {
PartyStateChangeResult result;
PartyError errorDetail;
PartyNetwork* network;
PartyLocalUser* localUser;
PartyInvitation* invitation;
void* asyncIdentifier;
}

Members
result PartyStateChangeResult

Indicates that the PartyNetwork::RevokeInvitation() operation succeeded or provides the reason that it failed.
errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
The human-readable form of this error detail can be retrieved via PartyManager::GetErrorMessage().
network PartyNetwork*
The network used in the call associated with this state change.
localUser PartyLocalUser*
The local user used to revoke the invitation.
invitation PartyInvitation*
The revoked invitation.
asyncIdentifier void*
The async identifier provided to the call associated with this state change.

Requirements
Header : Party.h

See also
Party members
PartyNetwork::RevokeInvitation
PartySetChatAudioInputCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the SetChatAudioInputCompleted type of state change.

Syntax
struct PartySetChatAudioInputCompletedStateChange : PartyStateChange {
PartyStateChangeResult result;
PartyError errorDetail;
PartyLocalChatControl* localChatControl;
PartyAudioDeviceSelectionType audioDeviceSelectionType;
PartyString audioDeviceSelectionContext;
void* asyncIdentifier;
}

Members
result PartyStateChangeResult

Indicates that the audio input configuration operation Succeeded or provides the reason that it failed.
errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
The human-readable form of this error detail can be retrieved via PartyManager::GetErrorMessage().
localChatControl PartyLocalChatControl*
The chat control used in the call associated with this state change.
audioDeviceSelectionType PartyAudioDeviceSelectionType
The audio device selection type provided to the call associated with this state change.
audioDeviceSelectionContext PartyString
The device context provided to the call associated with this state change.
asyncIdentifier void*
The async identifier provided to the call associated with this state change.

Requirements
Header : Party.h

See also
Party members
PartyLocalChatControl::SetAudioInput
PartySetChatAudioOutputCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the SetChatAudioOutputCompleted type of state change.

Syntax
struct PartySetChatAudioOutputCompletedStateChange : PartyStateChange {
PartyStateChangeResult result;
PartyError errorDetail;
PartyLocalChatControl* localChatControl;
PartyAudioDeviceSelectionType audioDeviceSelectionType;
PartyString audioDeviceSelectionContext;
void* asyncIdentifier;
}

Members
result PartyStateChangeResult

Indicates that the audio output configuration operation Succeeded or provides the reason that it failed.
errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
The human-readable form of this error detail can be retrieved via PartyManager::GetErrorMessage().
localChatControl PartyLocalChatControl*
The chat control used in the call associated with this state change.
audioDeviceSelectionType PartyAudioDeviceSelectionType
The audio device selection type provided to the call associated with this state change.
audioDeviceSelectionContext PartyString
The device context provided to the call associated with this state change.
asyncIdentifier void*
The async identifier provided to the call associated with this state change.

Requirements
Header : Party.h

See also
Party members
PartyLocalChatControl::SetAudioOutput
PartySetTextChatOptionsCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the PartySetTextChatOptionsCompleted type of state change.

Syntax
struct PartySetTextChatOptionsCompletedStateChange : PartyStateChange {
PartyStateChangeResult result;
PartyError errorDetail;
PartyLocalChatControl* localChatControl;
PartyTextChatOptions options;
void* asyncIdentifier;
}

Members
result PartyStateChangeResult

Indicates that the operation Succeeded or the reason that it failed.


errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
The human-readable form of this error detail can be retrieved via PartyManager::GetErrorMessage().
localChatControl PartyLocalChatControl*
The chat control used in the call associated with this state change.
options PartyTextChatOptions
The text chat options provided to the call associated with this state change.
asyncIdentifier void*
The async identifier provided to the call associated with this state change.

Requirements
Header : Party.h

See also
Party members
PartyLocalChatControl::SetTranscriptionOptions
PartySetTextToSpeechProfileCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the SetTextToSpeechProfileCompleted type of state change.

Syntax
struct PartySetTextToSpeechProfileCompletedStateChange : PartyStateChange {
PartyStateChangeResult result;
PartyError errorDetail;
PartyLocalChatControl* localChatControl;
PartySynthesizeTextToSpeechType type;
PartyString profileIdentifier;
void* asyncIdentifier;
}

Members
result PartyStateChangeResult

Indicates that the operation Succeeded or the reason that it failed.


On success, PartyLocalChatControl::GetTextToSpeechProfile() will return the full profile object corresponding to
the profile identifier provided to the PartyLocalChatControl::SetTextToSpeechProfile() call associated with this
state change. On failure, PartyLocalChatControl::GetTextToSpeechProfile() will return null.
errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
The human-readable form of this error detail can be retrieved via PartyManager::GetErrorMessage().
localChatControl PartyLocalChatControl*
The chat control used in the call associated with this state change.
type PartySynthesizeTextToSpeechType
The type of text-to-speech operation provided to the call associated with this state change.
profileIdentifier PartyString
The profile identifier provided to the call associated with this state change.
asyncIdentifier void*
The async identifier provided to the call associated with this state change.

Remarks
At most, one PartySetTextToSpeechProfileCompletedStateChange object will be returned in any state change
batch from PartyManager::StartProcessingStateChanges().

Requirements
Header : Party.h
See also
Party members
PartyLocalChatControl::SetTextToSpeechProfile
PartySetTranscriptionOptionsCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the SetTranscriptionOptionsCompleted type of state change.

Syntax
struct PartySetTranscriptionOptionsCompletedStateChange : PartyStateChange {
PartyStateChangeResult result;
PartyError errorDetail;
PartyLocalChatControl* localChatControl;
PartyVoiceChatTranscriptionOptions options;
void* asyncIdentifier;
}

Members
result PartyStateChangeResult

Indicates that the operation Succeeded or the reason that it failed.


On success, internal state has updated to reflect whether transcription operations should be attempted on behalf
of localChatControl . Success does not guarantee that transcription operations will complete successfully.
Failures to complete transcription operations will be exposed through the result field of the
PartyStateChangeType::VoiceChatTranscriptionReceived state change.
errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
The human-readable form of this error detail can be retrieved via PartyManager::GetErrorMessage().
localChatControl PartyLocalChatControl*
The chat control used in the call associated with this state change.
options PartyVoiceChatTranscriptionOptions
The transcription options provided to the call associated with this state change.
asyncIdentifier void*
The async identifier provided to the call associated with this state change.

Requirements
Header : Party.h

See also
Party members
PartyLocalChatControl::SetTranscriptionOptions
PartyStateChange
5/24/2022 • 2 minutes to read • Edit Online

A generic, base structure representation of an event or change in state.

Syntax
struct PartyStateChange {
PartyStateChangeType stateChangeType;
}

Members
stateChangeType PartyStateChangeType
The specific type of the state change represented.
Use this field to determine which corresponding derived structure is represented by this PartyStateChange
structure header.

Remarks
PartyStateChange structures are reported by PartyManager::StartProcessingStateChanges() for the title to
handle and then promptly pass back via the PartyManager::FinishProcessingStateChanges() method.

The stateChangeType field indicates which kind of state change occurred, and this base structure should then be
cast to a more specific derived structure to retrieve additional event-specific information.

Requirements
Header : Party.h

See also
Party members
PartyManager::StartProcessingStateChanges
PartyManager::FinishProcessingStateChanges
PartySynthesizeTextToSpeechCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the SynthesizeTextToSpeechCompleted type of state change.

Syntax
struct PartySynthesizeTextToSpeechCompletedStateChange : PartyStateChange {
PartyStateChangeResult result;
PartyError errorDetail;
PartyLocalChatControl* localChatControl;
PartySynthesizeTextToSpeechType type;
PartyString textToSynthesize;
void* asyncIdentifier;
}

Members
result PartyStateChangeResult

Indicates that the operation Succeeded or the reason that it failed.


errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
The human-readable form of this error detail can be retrieved via PartyManager::GetErrorMessage().
localChatControl PartyLocalChatControl*
The chat control used in the call associated with this state change.
type PartySynthesizeTextToSpeechType
The type of text-to-speech operation provided to the call associated with this state change.
textToSynthesize PartyString
The synthesized text provided to the call associated with this state change.
If the accompanying result was a success, the audio synthesized for this text has been queued in the audio
stream but may not have been transmitted yet.
asyncIdentifier void*
The async identifier provided to the call associated with this state change.

Requirements
Header : Party.h

See also
Party members
PartyLocalChatControl::SynthesizeTextToSpeech
PartyVoiceChatTranscriptionReceivedStateChange
5/24/2022 • 3 minutes to read • Edit Online

Information specific to the VoiceChatTranscriptionReceived type of state change.

Syntax
struct PartyVoiceChatTranscriptionReceivedStateChange : PartyStateChange {
PartyStateChangeResult result;
PartyError errorDetail;
PartyChatControl* senderChatControl;
uint32_t receiverChatControlCount;
PartyLocalChatControlArray receiverChatControls;
PartyAudioSourceType sourceType;
PartyString languageCode;
PartyString transcription;
PartyVoiceChatTranscriptionPhraseType type;
uint32_t translationCount;
PartyTranslation* translations;
}

Members
result PartyStateChangeResult

Indicates that the transcription operation Succeeded or provides the reason that it failed.
On success, the transcription field will be a string of non-zero length. On failure, the string will be empty.
Failure indicates that a transcription operation was attempted for the speaker but could not be completed. If
transcription is enabled at the request of the user associated with the chat control, and the transcription
messages are shown via UI, it is recommended that failures also be indicated to the user in order to provide
feedback as to whether transcriptions are pending or have failed.
errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
The human-readable form of this error detail can be retrieved via PartyManager::GetErrorMessage().
senderChatControl PartyChatControl*
The chat control object that originated the transcription message.
receiverChatControlCount uint32_t
The number of local receiver chat controls to which the transcription is addressed.
receiverChatControls PartyLocalChatControlArray
array of size receiverChatControlCount

The local receiver chat controls to which the transcription is addressed.


sourceType PartyAudioSourceType
The type of audio source this transcription represents.
The audio source type can optionally be used for game scenarios in which transcriptions from different source
types should be treated differently. For instance, different iconography may be shown depending on whether
the transcription is associated with microphone or text-to-speech audio.
languageCode PartyString
The language code of the transcription.
The language code will always be provided when the result field indicates success. Otherwise, the language
code will be an empty string.

The language code will be in BCP 47 format, such as en-US for English (United States). Supported language
codes are enumerated at https://docs.microsoft.com/azure/cognitive-services/speech-service/language-
support.
transcription PartyString
The transcribed voice chat text.
The string may be up to c_maxChatTextMessageLength characters long, not including the null terminator. The
string will always be empty when the result field indicates failures.
type PartyVoiceChatTranscriptionPhraseType
Indicates the phrase type of the text provided in the transcription field.
The type will always be PartyVoiceChatTranscriptionPhraseType::Final when the result field indicates failure.
translationCount uint32_t
The number of translations associated with the transcribed voice chat text.
Translations will be provided if PartyVoiceChatTranscriptionOptions::TranslateToLocalLanguage had previously
been specified via PartyLocalChatControl::SetTranscriptionOptions() on a chat control local to this device. There
may be more than one translation if multiple local chat controls have enabled translation and the local chat
controls have specified different languages via PartyLocalDevice::CreateChatControl(). In that case, the app can
compare the languageCode field of each PartyTranslation in translations against the language code, obtained
via PartyLocalChatControl::GetLanguage(), for each local chat control in receiverChatControls to determine the
target local chat control for each translation.
translations PartyTranslation*
array of size translationCount

An array containing the translations of the voice chat transcription string.


Translations will be provided if PartyVoiceChatTranscriptionOptions::TranslateToLocalLanguage had previously
been specified via PartyLocalChatControl::SetTranscriptionOptions() on a chat control local to this device. There
may be more than one translation if multiple local chat controls have enabled translation and the local chat
controls have specified different languages via PartyLocalDevice::CreateChatControl(). In that case, the app can
compare the languageCode field of each PartyTranslation in translations against the language code, obtained
via PartyLocalChatControl::GetLanguage(), for each local chat control in receiverChatControls to determine the
target local chat control for each translation.

A translation corresponding to the language for each chat control in receiverChatControls that has enabled
translation will be provided, even if the speaking chat control's language is the same as the local chat control's
language. In such a case, the transcription and translation strings will be identical.

Requirements
Header : Party.h

See also
Party members
PartyLocalDevice::CreateChatControl
PartyLocalChatControl::SetTranscriptionOptions
PartyAudioDeviceSelectionType
5/24/2022 • 2 minutes to read • Edit Online

Options for selecting audio devices

Syntax
enum class PartyAudioDeviceSelectionType
{
None = 0,
SystemDefault = 1,
PlatformUserDefault = 2,
Manual = 3,
}

Constants
C O N STA N T DESC RIP T IO N

None Indicate that no audio device should be used.

SystemDefault Select audio device based on the platform settings.

If this selection type is used for


PartyLocalChatControl::SetAudioInput() or
PartyLocalChatControl::SetAudioOutput() then the
audioDeviceSelectionContext should be nullptr.

PlatformUserDefault Select audio device based on the platform and user settings.

If this selection type is used for


PartyLocalChatControl::SetAudioInput() or
PartyLocalChatControl::SetAudioOutput() then the
audioDeviceSelectionContext must be a platform specific
user context.

Manual Audio device specified by the game.

If this selection type is used for


PartyLocalChatControl::SetAudioInput() or
PartyLocalChatControl::SetAudioOutput() then the
audioDeviceSelectionContext must be the identifier of the
audio device to use.

Note that on iOS and Android, setting a manual input device


is an illegal operation. Using this with
PartyLocalChatControl::SetAudioInput() on Android and iOS
will result in an error indicating that the device selection type
is not supported.

Requirements
Header : Party.h
See also
Party members
PartyLocalChatControl::SetAudioInput
PartyLocalChatControl::SetAudioOutput
PartyAudioInputState
5/24/2022 • 2 minutes to read • Edit Online

States of an audio input associated with a local chat control.

Syntax
enum class PartyAudioInputState
{
NoInput = 0,
Initialized = 1,
NotFound = 2,
UserConsentDenied = 3,
UnsupportedFormat = 4,
AlreadyInUse = 5,
UnknownError = 6,
}

Constants
C O N STA N T DESC RIP T IO N

NoInput No audio input was specified.

Initialized The audio input was successfully initialized.

NotFound The audio input wasn't found.

This can occur if the input was removed while in use. When
in this state, the chat control will subscribe to audio device
changes and use the specified input if it can be found at a
later time.

UserConsentDenied The user didn't give permission to access the input.

UnsupportedFormat The input doesn't provide a supported format.

AlreadyInUse The audio input device is already in use by another chat


control.

UnknownError Initializing the input resulted in an unknown error.

Requirements
Header : Party.h

See also
Party members
PartyAudioOutputState
5/24/2022 • 2 minutes to read • Edit Online

States of an audio output associated with a local chat control.

Syntax
enum class PartyAudioOutputState
{
NoOutput = 0,
Initialized = 1,
NotFound = 2,
UnsupportedFormat = 3,
AlreadyInUse = 4,
UnknownError = 5,
}

Constants
C O N STA N T DESC RIP T IO N

NoOutput No audio output was specified.

Initialized The audio output was successfully initialized.

NotFound The audio output wasn't found.

This can occur if the output was removed while in use. When
in this state, the chat control will subscribe to audio device
changes and use the specified output if it can be found at a
later time.

UnsupportedFormat The output doesn't provide a supported sample rate.

AlreadyInUse The audio output device is already in use by another chat


control.

UnknownError Initializing the output resulted in an unknown error.

Requirements
Header : Party.h

See also
Party members
PartyAudioSampleType
5/24/2022 • 2 minutes to read • Edit Online

Types of Party audio samples.

Syntax
enum class PartyAudioSampleType
{
Integer = 0,
Float = 1,
}

Constants
C O N STA N T DESC RIP T IO N

Integer Integer PCM format.

Float IEEE floating-point PCM format.

Requirements
Header : Party.h

See also
Party members
PartyAudioSourceType
5/24/2022 • 2 minutes to read • Edit Online

Types of Party audio sources.

Syntax
enum class PartyAudioSourceType
{
Microphone = 0,
TextToSpeech = 1,
}

Constants
C O N STA N T DESC RIP T IO N

Microphone A microphone audio source.

Audio captured from a microphone or recording device,


configured via PartyLocalChatControl::SetAudioInput(), or
optionally submitted to a capture sink, via
PartyAudioManipulationSinkStream::SubmitBuffer(), is
treated as microphone audio.

TextToSpeech A text-to-speech audio source.

Audio that is generated by


PartyLocalChatControl::SynthesizeTextToSpeech() is treated
as text-to-speech audio.

Requirements
Header : Party.h

See also
Party members
PartyChatControlChatIndicator
5/24/2022 • 2 minutes to read • Edit Online

Audio states for a target chat control in relation to a local chat control.

Syntax
enum class PartyChatControlChatIndicator
{
Silent = 0,
Talking = 1,
IncomingVoiceDisabled = 2,
IncomingCommunicationsMuted = 3,
NoRemoteInput = 4,
RemoteAudioInputMuted = 5,
}

Constants
C O N STA N T DESC RIP T IO N

Silent The target chat control isn't generating voice audio.

Talking The target chat control is generating voice audio.

IncomingVoiceDisabled The local chat control is not configured to receive audio from
the target chat control.

IncomingCommunicationsMuted The target chat control has been muted by the local chat
control.

NoRemoteInput The target chat control does not have an audio input.

RemoteAudioInputMuted The target chat control has an audio input but has muted it.

Requirements
Header : Party.h

See also
Party members
PartyChatPermissionOptions
5/24/2022 • 2 minutes to read • Edit Online

Options for defining the communication relationship between two chat controls.

Syntax
enum class PartyChatPermissionOptions
{
None = 0x0,
SendMicrophoneAudio = 0x1,
SendTextToSpeechAudio = 0x2,
SendAudio = SendMicrophoneAudio | SendTextToSpeechAudio,
ReceiveMicrophoneAudio = 0x4,
ReceiveTextToSpeechAudio = 0x8,
ReceiveAudio = ReceiveMicrophoneAudio | ReceiveTextToSpeechAudio,
ReceiveText = 0x10,
}

Constants
C O N STA N T DESC RIP T IO N

None No chat communication between the local chat control and


the target chat control is allowed.

SendMicrophoneAudio Microphone audio communication from the local chat


control to the target chat control is allowed.

For most game scenarios, either all or no audio


communication should be sent and SendAudio should be
used instead. This flag can be used for game scenarios where
microphone audio should be sent to the target chat control,
but other types of audio should not.

Audio optionally submitted to a capture sink via


PartyAudioManipulationSinkStream::SubmitBuffer() is treated
as microphone audio when applying chat permissions and
determining which chat controls should receive the audio.

SendTextToSpeechAudio Text-to-speech audio communication from the local chat


control to the target chat control is allowed.

For most game scenarios, either all or no audio


communication should be sent and SendAudio should be
used instead. This flag can be used for game scenarios where
text-to-speech audio should be sent to the target chat
control, but other types of audio should not.

SendAudio All audio communication from the local chat control to the
target chat control is allowed.

This flag is equivalent to


SendMicrophoneAudio | SendTextToSpeechAudio .
C O N STA N T DESC RIP T IO N

ReceiveMicrophoneAudio Microphone audio communication from the target chat


control to the local chat control is allowed.

For most game scenarios, either all or no audio


communication should be received and ReceiveAudio
should be used instead. This flag can be used for game
scenarios where microphone audio should be received from
the target chat control, but other types of audio should not.

Audio optionally submitted to a capture sink via


PartyAudioManipulationSinkStream::SubmitBuffer() is treated
as microphone audio when applying chat permissions and
determining which chat controls should receive the audio.

ReceiveTextToSpeechAudio Text-to-speech audio communication from the target chat


control to the local chat control is allowed.

For most game scenarios, either all or no audio


communication should be received and ReceiveAudio
should be used instead. This flag can be used for game
scenarios where text-to-speech audio should be received
from the target chat control, but other types of audio should
not.

ReceiveAudio Audio communication from the target chat control to the


local chat control is allowed.

This flag is equivalent to


ReceiveMicrophoneAudio | ReceiveTextToSpeechAudio .

ReceiveText Text communication from the target chat control to the local
chat control is allowed.

Requirements
Header : Party.h

See also
Party members
PartyChatTextReceivedOptions
5/24/2022 • 2 minutes to read • Edit Online

Flags describing the received text message in PartyChatTextReceivedStateChange.

Syntax
enum class PartyChatTextReceivedOptions
{
None = 0x0,
FilteredOffensiveTerms = 0x1,
FilteredEntireMessage = 0x2,
FilteredDueToError = 0x4,
}

Constants
C O N STA N T DESC RIP T IO N

None No flags are specified.

FilteredOffensiveTerms Offensive terms were found and replaced with asterisks.

This value is exclusive to FilteredEntireMessage and


FilteredDueToError.

FilteredEntireMessage The incoming text chat was unable to filter specific terms,
and the entire text has been replaced by asterisks.

This option occurs when the moderation service was not


able to identify specific terms to filter, but has still identified
the text as being offensive.

This value is exclusive to FilteredOffensiveTerms and


FilteredDueToError.

FilteredDueToError The incoming text was unable to be filtered, and the entire
text has been replaced by asterisks.

This value is exclusive to FilteredOffensiveTerms and


FilteredEntireMessage.

Requirements
Header : Party.h

See also
Party members
PartyChatTextReceivedStateChange
PartyDestroyedReason
5/24/2022 • 2 minutes to read • Edit Online

Reasons an object might be destroyed.

Syntax
enum class PartyDestroyedReason
{
Requested = 0,
Disconnected = 1,
Kicked = 2,
DeviceLostAuthentication = 3,
CreationFailed = 4,
}

Constants
C O N STA N T DESC RIP T IO N

Requested The invitation, endpoint, device, network, or chat control is


being destroyed gracefully by request.

Disconnected The invitation, endpoint, device, network, or chat control is


being destroyed because connectivity to the transparent
cloud relay server was lost.

Kicked The device or user that the invitation, endpoint, or chat


control depended upon was kicked.

DeviceLostAuthentication No local users on the local device were authenticated on the


network, so the local device lost visibility to the remotely
managed invitation, endpoint, device, or chat control.

Even though the local object referring to the remotely


managed object has been destroyed, the remotely managed
object may still exist in the network.

CreationFailed The invitation or endpoint creation failed asynchronously, so


the local object has been destroyed.

Requirements
Header : Party.h

See also
Party members
PartyDeviceConnectionType
5/24/2022 • 2 minutes to read • Edit Online

The type of connection used for transmitting endpoint message or chat data to a device.

Syntax
enum class PartyDeviceConnectionType
{
RelayServer = 0,
DirectPeerConnection = 1,
}

Constants
C O N STA N T DESC RIP T IO N

RelayServer All communication is transmitted via a transparent cloud


relay server.

DirectPeerConnection All communication is transmitted using a direct peer-to-peer


connection.

Requirements
Header : Party.h

See also
Party members
PartyNetwork::GetDeviceConnectionType
PartyDirectPeerConnectivityOptions
5/24/2022 • 5 minutes to read • Edit Online

Flags controlling the attempted use of direct peer-to-peer connectivity among devices in a network.

Syntax
enum class PartyDirectPeerConnectivityOptions : int32_t
{
None = 0x0,
SamePlatformType = 0x1,
DifferentPlatformType = 0x2,
AnyPlatformType = SamePlatformType | DifferentPlatformType,
SameEntityLoginProvider = 0x4,
DifferentEntityLoginProvider = 0x8,
AnyEntityLoginProvider = SameEntityLoginProvider | DifferentEntityLoginProvider,
}

Constants
C O N STA N T DESC RIP T IO N

None No flags are specified.

The absence of flags means that no direct peer connectivity


attempts are permitted. All endpoint messages and chat
data between devices will always be transmitted via
transparent cloud relay servers, and no IP address
information will ever be exchanged.

SamePlatformType Direct peer-to-peer connections may be attempted between


devices of the same platform type.

A pair of devices will attempt to establish direct peer-to-peer


connections if they're identified as having the same type of
hardware and/or OS platform (e.g., Windows PCs, Xbox
gaming consoles, iOS-based mobile devices) associated with
the specific Party library they use.

Note that this flag does not permit any direct peer-to-peer
connectivity attempts by itself. It must be combined with
one or both of the SameEntityLoginProvider and
DifferentEntityLoginProvider flags.
C O N STA N T DESC RIP T IO N

DifferentPlatformType Direct peer-to-peer connections may be attempted between


devices with differing platform types.

A pair of devices will attempt to establish direct peer-to-peer


connections if they're identified as having different types of
hardware and/or OS platforms (e.g., Windows PCs, Xbox
gaming consoles, iOS-based mobile devices) associated with
the specific Party libraries each device uses.

Note that this flag does not permit any direct peer-to-peer
connectivity attempts by itself. It must be combined with
one or both of the SameEntityLoginProvider and
DifferentEntityLoginProvider flags.

AnyPlatformType Direct peer-to-peer connections may be attempted between


devices regardless of their platform types.

This flag is equivalent to


SamePlatformType | DifferentPlatformType .

SameEntityLoginProvider Direct peer-to-peer connections may be attempted between


devices that have authenticated user PlayFab Entity IDs that
were logged in using the same provider.

A device that's initially authenticating a local user into the


network will attempt to establish direct peer-to- peer
connections with remote devices that have at least one
authenticated user PlayFab Entity ID that was logged in
using the same provider (e.g., Xbox Live, Facebook, iOS,
Google) as the newly authenticating user.

Note that this flag does not permit any direct peer-to-peer
connectivity attempts by itself. It must be combined with
one or both of the SamePlatformType and
DifferentPlatformType flags.

DifferentEntityLoginProvider Direct peer-to-peer connections may be attempted between


devices with authenticated user PlayFab Entity IDs that that
were logged in using different providers.

A device that's initially authenticating a local user into the


network will attempt to establish direct peer-to- peer
connections with remote devices that do not have any
authenticated user PlayFab Entity IDs that were logged in
using the same provider (e.g., Xbox Live, Facebook, iOS,
Google) as the newly authenticating user.

Note that this flag does not permit any direct peer-to-peer
connectivity attempts by itself. It must be combined with
one or both of the SamePlatformType and
DifferentPlatformType flags.
C O N STA N T DESC RIP T IO N

AnyEntityLoginProvider Direct peer-to-peer connections may be attempted between


devices regardless of the provider used to login
authenticated user PlayFab Entity IDs.

This flag is equivalent to


SameEntityLoginProvider |
DifferentEntityLoginProvider
.

Remarks
As part of successfully authenticating an initial user into a network, a device may attempt to establish direct
peer-to-peer connections with other devices already participating in the network when permitted by these flags
declared in the network's PartyNetworkConfiguration structure. For attempts that are successful, endpoint
messages and chat data between the devices will be transmitted using those direct connections. For attempts
that fail due to environmental incompatibilities between the devices, all communication between those devices
will be transmitted via transparent cloud relay servers instead. If the devices aren't permitted to attempt direct
peer connections by these flags, then they never exchange IP address information and will always transmit
endpoint messages and chat data via transparent cloud relay servers.

You can determine whether the local device actually established a direct peer-to-peer connection to a specific
remote device by calling PartyNetwork::GetDeviceConnectionType().

Successful direct peer connectivity may provide lower latency between some devices, though attempting to
establish it also requires users to disclose their devices' IP addresses to others, which may be a concern for
privacy or for enabling malicious users to potentially attack peers' devices and Internet connections outside of
the title. It also may not be permitted on certain platforms for policy reasons. Be sure to use the appropriate
flags for your performance and security goals.

Besides a specific network's PartyNetworkConfiguration::directPeerConnectivityOptions value, the flags may


optionally be further constrained by a device for all networks into which it authenticates by using
PartyManager::SetOption() to set PartyOption::LocalDeviceDirectPeerConnectivityOptionsMask. All flags are
evaluated using a bitwise AND operation. That is, a particular flag is actually only in effect for a given network's
pair of devices if it's enabled in three places: the network's PartyNetworkConfiguration structure, and both
devices' respective local mask options. Even if the Party network permits direct peer connectivity of the relevant
form, either device can unilaterally opt out of the IP address disclosure and direct connection attempts between
them by not enabling the flag. The PartyOption::LocalDeviceDirectPeerConnectivityOptionsMask value defaults
to permitting all direct peer connections enabled by networks, so you only need to configure it if you have
device-specific requirements to prevent some or all direct peer connectivity involving it.

To avoid excessive resource consumption, the Party library will also internally prevent any given device from
attempting to establish more than c_maxDirectPeerConnectionsPerDevice direct peer connections across all
networks in which it's currently participating, even if permitted by these flags. This doesn't affect the device's
ability to participate in large or multiple networks with additional remote devices. Communication with
additional devices will simply be transmitted via transparent cloud relay servers.

It's recommended that you don't actively enforce the availability of a direct peer-to-peer connection for any
given pair of devices (i.e., don't call PartyNetwork::LeaveNetwork() if PartyNetwork::GetDeviceConnectionType()
reports a value other than PartyDeviceConnectionType::DirectPeerConnection) since the specific underlying
transmission method in use doesn't alter the overall logical ability to communicate. If your game design has
stringent requirements for maximum message latency that encourage direct peer connectivity, it's better to take
action on the current concrete observations of that latency as reported by the
PartyEndpointStatistic::AverageDeviceRoundTripLatencyInMilliseconds statistic rather than make abstract
assumptions based on transmission mechanism. Otherwise you might continually hinder users trying to play
with the same set of friends who always need to use nearby transparent cloud relay servers due to
environmental factors beyond their control.

Requirements
Header : Party.h

See also
Party members
PartyNetworkConfiguration
PartyOption::LocalDeviceDirectPeerConnectivityOptionsMask
PartyManager::SetOption
PartyEndpointStatistic::AverageDeviceRoundTripLatencyInMilliseconds
PartyLocalEndpoint::GetEndpointStatistics
PartyEndpointStatistic
5/24/2022 • 5 minutes to read • Edit Online

Types of statistics that can be retrieved for an endpoint.

Syntax
enum class PartyEndpointStatistic
{
CurrentlyQueuedSendMessages = 0,
CurrentlyQueuedSendMessageBytes = 1,
CurrentlyActiveSendMessages = 2,
CurrentlyActiveSendMessageBytes = 3,
TimedOutSendMessages = 4,
TimedOutSendMessageBytes = 5,
CanceledSendMessages = 6,
CanceledSendMessageBytes = 7,
AverageDeviceRoundTripLatencyInMilliseconds = 8,
}

Constants
C O N STA N T DESC RIP T IO N

CurrentlyQueuedSendMessages The number of messages currently queued by


PartyLocalEndpoint::SendMessage() but not yet transmitted
from the local endpoint to the specified target endpoints.

For efficiency, only a single message is queued by


PartyLocalEndpoint::SendMessage() when sending to
multiple target endpoints at once via the transparent cloud
relay server. If two or more of those endpoints are specified
to PartyLocalEndpoint::GetEndpointStatistics() when
querying for this statistic, the message will only be counted
a single time rather than multiplied per target endpoint.

CurrentlyQueuedSendMessageBytes The number of bytes of data in messages currently queued


by PartyLocalEndpoint::SendMessage() but not yet
transmitted from the local endpoint to the specified target
endpoints.

For efficiency, only a single message is queued by


PartyLocalEndpoint::SendMessage() when sending to
multiple target endpoints at once via the transparent cloud
relay server. If two or more of those endpoints are specified
to PartyLocalEndpoint::GetEndpointStatistics() when
querying for this statistic, the message bytes will only be
counted a single time rather than multiplied per target
endpoint.
C O N STA N T DESC RIP T IO N

CurrentlyActiveSendMessages The number of PartyLocalEndpoint::SendMessage()


messages from the local endpoint to the specified target
endpoints that are currently being transmitted or still have
more local state changes to be processed.

A message is considered "active" as soon as its first byte has


been placed in a packet that is being transmitted. It remains
active until transmission completes and the local
PartyDataBuffersReturnedStateChange for it (if applicable)
has been returned to
PartyManager::FinishProcessingStateChanges().

For efficiency, only a single message is tracked per


PartyLocalEndpoint::SendMessage() when sending to
multiple target endpoints at once via the transparent cloud
relay server. If two or more of those endpoints are specified
to PartyLocalEndpoint::GetEndpointStatistics() when
querying for this statistic, the message will only be counted
a single time rather than multiplied per target endpoint.

CurrentlyActiveSendMessageBytes The number of bytes of data in


PartyLocalEndpoint::SendMessage() messages from the local
endpoint to the specified target endpoints that are currently
being transmitted or still have more local state changes to
be processed.

A message is considered "active" as soon as its first byte has


been placed in a packet that is being transmitted. It remains
active until transmission completes and the local
PartyDataBuffersReturnedStateChange for it (if applicable)
has been returned to
PartyManager::FinishProcessingStateChanges().

For efficiency, only a single message is tracked per


PartyLocalEndpoint::SendMessage() when sending to
multiple target endpoints at once via the transparent cloud
relay server. If two or more of those endpoints are specified
to PartyLocalEndpoint::GetEndpointStatistics() when
querying for this statistic, the message bytes will only be
counted a single time rather than multiplied per target
endpoint.
C O N STA N T DESC RIP T IO N

TimedOutSendMessages The total number of PartyLocalEndpoint::SendMessage()


messages from the local endpoint to the specified target
endpoints that were ever discarded for exceeding their send
queue timeouts without being transmitted.

A message's send queue timeout is specified using


PartySendMessageQueuingConfiguration::timeoutInMillseco
nds when calling PartyLocalEndpoint::SendMessage().

For efficiency, only a single message is queued by


PartyLocalEndpoint::SendMessage() when sending to
multiple target endpoints at once via the transparent cloud
relay server. If two or more of those endpoints are specified
to PartyLocalEndpoint::GetEndpointStatistics() when
querying for this statistic, the message will only be counted
a single time rather than multiplied per target endpoint.

When querying this statistic for all target endpoints by


providing a zero-entry array to
PartyLocalEndpoint::GetEndpointStatistics(), note that only
endpoints that currently exist will be included. If an endpoint
that had timed out messages gets destroyed between
queries, this count might be perceived as "going backward".

TimedOutSendMessageBytes The total number of bytes of data in


PartyLocalEndpoint::SendMessage() messages from the local
endpoint to the specified target endpoints that were ever
discarded for exceeding their send queue timeouts without
being transmitted.

A message's send queue timeout is specified using


PartySendMessageQueuingConfiguration::timeoutInMillseco
nds when calling PartyLocalEndpoint::SendMessage().

For efficiency, only a single message is queued by


PartyLocalEndpoint::SendMessage() when sending to
multiple target endpoints at once via the transparent cloud
relay server. If two or more of those endpoints are specified
to PartyLocalEndpoint::GetEndpointStatistics() when
querying for this statistic, the message bytes will only be
counted a single time rather than multiplied per target
endpoint.

When querying this statistic for all target endpoints by


providing a zero-entry array to
PartyLocalEndpoint::GetEndpointStatistics(), note that only
endpoints that currently exist will be included. If an endpoint
that had timed out messages gets destroyed between
queries, this count might be perceived as "going backward".
C O N STA N T DESC RIP T IO N

CanceledSendMessages The total number of PartyLocalEndpoint::SendMessage()


messages from the local endpoint to the specified target
endpoints that were ever canceled.

Messages are canceled before being transmitted by the


application calling PartyLocalEndpoint::CancelMessages()
with a matching filter expression.

For efficiency, only a single message is queued by


PartyLocalEndpoint::SendMessage() when sending to
multiple target endpoints at once via the PartyNetwork
transparent cloud relay server. If two or more of those
endpoints are specified to
PartyLocalEndpoint::GetEndpointStatistics() when querying
for this statistic, the message will only be counted a single
time rather than multiplied per target endpoint.

When querying this statistic for all target endpoints by


providing a zero-entry array to
PartyLocalEndpoint::GetEndpointStatistics(), note that only
endpoints that currently exist will be included. If an endpoint
that had canceled messages gets destroyed between
queries, this count might be perceived as "going backward".

CanceledSendMessageBytes The total number of bytes of data in


PartyLocalEndpoint::SendMessage() messages from the local
endpoint to the specified target endpoints that were ever
canceled.

Messages are canceled before being transmitted by the


application calling PartyLocalEndpoint::CancelMessages()
with a matching filter expression.

For efficiency, only a single message is queued by


PartyLocalEndpoint::SendMessage() when sending to
multiple target endpoints at once via the PartyNetwork
transparent cloud relay server. If two or more of those
endpoints are specified to
PartyLocalEndpoint::GetEndpointStatistics() when querying
for this statistic, the message bytes will only be counted a
single time rather than multiplied per target endpoint.

When querying this statistic for all target endpoints by


providing a zero-entry array to
PartyLocalEndpoint::GetEndpointStatistics(), note that only
endpoints that currently exist will be included. If an endpoint
that had canceled messages gets destroyed between
queries, this count might be perceived as "going backward".
C O N STA N T DESC RIP T IO N

AverageDeviceRoundTripLatencyInMilliseconds The current moving average round trip latency ("ping time")
in milliseconds to the endpoint's owning device.

This latency represents a moving average of the time it


currently takes for this local device to send a message and
receive a response from the target endpoint's device.

This statistic can only be queried for exactly one target


endpoint at a time. The
PartyLocalEndpoint::GetEndpointStatistics() method will fail if
multiple targets are provided, or if a zero-entry array is
provided to attempt to query all current endpoints.

You can also determine the local device's average round trip
latency to the network's transparent cloud relay server by
using PartyNetwork::GetNetworkStatistics() to retrieve the
PartyNetworkStatistic::AverageRelayServerRoundTripLatencyI
nMilliseconds statistic.

Requirements
Header : Party.h

See also
Party members
PartyNetworkStatistic
PartySendMessageQueuingConfiguration
PartyLocalEndpoint::SendMessage
PartyLocalEndpoint::GetEndpointStatistics
PartyNetwork::GetNetworkStatistics
PartyGender
5/24/2022 • 2 minutes to read • Edit Online

Genders for text to speech profiles.

Syntax
enum class PartyGender
{
Neutral = 0,
Female = 1,
Male = 2,
}

Constants
C O N STA N T DESC RIP T IO N

Neutral The text to speech profile represents a gender-neutral voice.

Female The text to speech profile represents a female voice.

Male The text to speech profile represents a male voice.

Requirements
Header : Party.h

See also
Party members
PartyTextToSpeechProfile
PartyInvitationRevocability
5/24/2022 • 2 minutes to read • Edit Online

Options for who may revoke an invitation.

Syntax
enum class PartyInvitationRevocability
{
Creator = 0,
Anyone = 1,
}

Constants
C O N STA N T DESC RIP T IO N

Creator The invitation may only be revoked by the PartyLocalUser


that created the invitation.

Anyone The invitation may be revoked by any authenticated user in


the network.

Requirements
Header : Party.h

See also
Party members
PartyNetwork::RevokeInvitation
PartyInvitation
PartyLocalUser
PartyLocalChatControlChatIndicator
5/24/2022 • 2 minutes to read • Edit Online

Audio states for a local chat control.

Syntax
enum class PartyLocalChatControlChatIndicator
{
Silent = 0,
Talking = 1,
AudioInputMuted = 2,
NoAudioInput = 3,
}

Constants
C O N STA N T DESC RIP T IO N

Silent The local chat control is not generating voice audio.

Talking The local chat control is generating voice audio.

AudioInputMuted The local chat control's audio input is muted.

NoAudioInput Either no audio input has been specified for the local chat
control, or initializing the specified input failed.

This may be due to the user removing a physical audio


device, or an error during audio device initialization. A
PartyLocalChatAudioInputChangedStateChange or
PartyLocalChatAudioOutputChangedStateChange with more
granular information will have been provided prior to the
chat indicator changing to this value.

Requirements
Header : Party.h

See also
Party members
PartyLocalUdpSocketBindAddressOptions
5/24/2022 • 2 minutes to read • Edit Online

Additional options to control how the Party library binds to the UDP socket specified by the
PartyLocalUdpSocketBindAddressConfiguration structure.

Syntax
enum class PartyLocalUdpSocketBindAddressOptions
{
None = 0x0,
ExcludeGameCorePreferredUdpMultiplayerPort = 0x1,
}

Constants
C O N STA N T DESC RIP T IO N

None No flags are specified.

This value is the default if a


PartyLocalUdpSocketBindAddressConfiguration structure
has not been explicitly set.

ExcludeGameCorePreferredUdpMultiplayerPort Don't default to using the Microsoft Game Core preferred


UDP multiplayer port when the port is unspecified.

In the Microsoft Game Core version of the Party library,


when the port field of the
PartyLocalUdpSocketBindAddressConfiguration structure is
0, this flag informs the Party library to not use the Game
Core preferred UDP multiplayer port. In other versions of
the Party library or if the port port is non-zero, this flag
must not be set.

Requirements
Header : Party.h

See also
Party members
PartyLocalUdpSocketBindAddressConfiguration
PartyLocalUserRemovedReason
5/24/2022 • 2 minutes to read • Edit Online

Reasons for removing a local user from a network.

Syntax
enum class PartyLocalUserRemovedReason
{
AuthenticationFailed = 0,
RemoveLocalUser = 1,
DestroyLocalUser = 2,
DestroyNetwork = 3,
}

Constants
C O N STA N T DESC RIP T IO N

AuthenticationFailed The local user is being removed because


PartyNetwork::AuthenticateLocalUser() asynchronously
failed.

RemoveLocalUser The local user is being removed because the title called
PartyNetwork::RemoveLocalUser().

DestroyLocalUser The local user is being removed because the title called
PartyManager::DestroyLocalUser().

DestroyNetwork The local user is being removed because the network is


being destroyed.

Requirements
Header : Party.h

See also
Party members
PartyNetwork::AuthenticateLocalUser
PartyNetwork::RemoveLocalUser
PartyManager::DestroyLocalUser
PartyMessageReceivedOptions
5/24/2022 • 2 minutes to read • Edit Online

Flags describing how a message was received.

Syntax
enum class PartyMessageReceivedOptions : int32_t
{
None = 0x0000,
GuaranteedDelivery = 0x0001,
SequentialDelivery = 0x0002,
RequiredFragmentation = 0x0004,
}

Constants
C O N STA N T DESC RIP T IO N

None There is no additional message reception information.

GuaranteedDelivery The message's delivery was guaranteed.

This flag's presence or absence represents the actual delivery


mode. The Party library may occasionally adjust messages
internally to use guaranteed delivery even if
PartySendMessageOptions::GuaranteedDelivery was not
originally specified to PartyLocalEndpoint::SendMessage(). It
will never disable guaranteed delivery if it had originally been
requested, however.

SequentialDelivery The message was delivered using sequencing information.

This flag's presence or absence represents the actual delivery


mode. The Party library may occasionally adjust messages
internally to sequential delivery even if
PartySendMessageOptions::SequentialDelivery was not
originally specified to PartyLocalEndpoint::SendMessage(). It
will never disable sequential delivery if it had originally been
requested, however.

RequiredFragmentation The message was larger than could fit in available space in a
single packet and needed to be split across multiple packets
for delivery.

The Party library automatically fragments and reassembles


large messages that exceed the maximum size supported by
the environment so that callers are not required to manage
this. However, there is a small amount of overhead
associated with fragmentation. Callers that are able to send
smaller messages or otherwise naturally break up large state
payloads efficiently themselves may wish to do so.
Requirements
Header : Party.h

See also
Party members
PartyEndpointMessageReceivedStateChange
PartyLocalEndpoint::SendMessage
PartyNetworkStatistic
5/24/2022 • 8 minutes to read • Edit Online

Types of statistics that can be retrieved for a network.

Syntax
enum class PartyNetworkStatistic
{
AverageRelayServerRoundTripLatencyInMilliseconds = 0,
SentProtocolPackets = 1,
SentProtocolBytes = 2,
RetriedProtocolPackets = 3,
RetriedProtocolBytes = 4,
DroppedProtocolPackets = 5,
ReceivedProtocolPackets = 6,
ReceivedProtocolBytes = 7,
CurrentlyQueuedSendMessages = 8,
CurrentlyQueuedSendMessageBytes = 9,
CurrentlyActiveSendMessages = 10,
CurrentlyActiveSendMessageBytes = 11,
TimedOutSendMessages = 12,
TimedOutSendMessageBytes = 13,
CanceledSendMessages = 14,
CanceledSendMessageBytes = 15,
}

Constants
C O N STA N T DESC RIP T IO N

AverageRelayServerRoundTripLatencyInMilliseconds The current moving average round trip latency ("ping time")
in milliseconds to the network's cloud relay server.

This latency represents a moving average of the time it


currently takes for this local device to send a message and
receive a response from the transparent cloud relay server.

You can also determine a particular local endpoint's average


round trip latency to another endpoint in the network by
using PartyLocalEndpoint::GetEndpointStatistics() to retrieve
the
PartyEndpointStatistic::AverageDeviceRoundTripLatencyInMill
iseconds statistic.
C O N STA N T DESC RIP T IO N

SentProtocolPackets The total number of internal protocol packets ever


transmitted to remote devices as part of this network.

This statistic represents the total number of internal protocol


packets transmitted by the local device for any network
reason. It includes packets generated as a result of
PartyLocalEndpoint::SendMessage() calls but doesn't
necessarily have a one-to-one correspondence with them
because multiple small messages may be coalesced together
into a single packet, or a large message may be fragmented
into multiple packets depending on configuration and
environmental factors. Further, packets may be used to carry
chat or other internal library functionality (e.g., API operation
support messages, protocol acknowledgements or retries)
on behalf of the application without an explicit
PartyLocalEndpoint::SendMessage() call.

This statistic does not include any packets generated for


HTTP web client operations that are used internally by the
Party library for some aspects of authentication,
management transactions, speech-to-text transcription, and
text-to-speech synthesis.

SentProtocolBytes The total number of internal protocol bytes ever transmitted


to remote devices as part of this network.

This statistic represents the total number of bytes in internal


protocol packets transmitted by the local device for any
network reason. This size includes
PartyLocalEndpoint::SendMessage() payloads but also their
internal protocol overhead, as well as any chat or other
internal library functionality needed (e.g., API operation
support messages, protocol acknowledgements or retries)
on behalf of the application without an explicit
PartyLocalEndpoint::SendMessage() call.

The reported value does not include the packet overhead for
Internet protocols (e.g., UDP, IP) or that of lower level media
over which the Party library internal protocol operates.

This statistic does not include the sizes of any packets


generated for HTTP web client operations that are used
internally by the Party library for some aspects of
authentication, management transactions, speech-to-text
transcription, and text-to-speech synthesis.
C O N STA N T DESC RIP T IO N

RetriedProtocolPackets The total number of internal protocol packets ever re-


transmitted to remote devices as part of this network.

This statistic represents the total number of internal protocol


packet retransmissions by the local device due to apparent
environmental loss of an earlier attempt. The Party library
will only retry lost packets that contain application messages
sent with PartySendMessageOptions::GuaranteedDelivery or
internal library messages with similar delivery requirements.

This statistic does not include any retries of packets


generated for HTTP web client operations that are used
internally by the Party library for some aspects of
authentication, management transactions, speech-to-text
transcription, and text-to-speech synthesis.

RetriedProtocolBytes The total number of internal protocol bytes ever re-


transmitted to remote devices as part of this network.

This statistic represents the total number of bytes in internal


protocol packet retransmissions by the local device due to
apparent environmental loss of an earlier attempt. This size
includes payloads of application messages sent with
PartySendMessageOptions::GuaranteedDelivery or internal
library messages with similar delivery requirements.

The reported value does not include the retried packet


overhead for Internet protocols (e.g., UDP, IP) or that of
lower level media over which the Party library internal
protocol operates.

This statistic does not include the sizes of any retried packets
generated for HTTP web client operations that are used
internally by the Party library for some aspects of
authentication, management transactions, speech-to-text
transcription, and text-to-speech synthesis.

DroppedProtocolPackets The total number of internal protocol packets to remote


devices in this network that are believed to have been
dropped.

This statistic represents the total number of internal protocol


packet transmissions by the local device that were
attempted but appeared to suffer environmental loss. They
may or may not have been retried (see
RetriedProtocolPackets).

This statistic does not include any dropped packets that


were generated for HTTP web client operations used
internally by the Party library for some aspects of
authentication, management transactions, speech-to-text
transcription, and text-to-speech synthesis.
C O N STA N T DESC RIP T IO N

ReceivedProtocolPackets The total number of internal protocol packets ever received


from remote devices as part of this network.

This statistic represents the total number of internal protocol


packets received by the local device for any network reason,
which does not have a one-to-one correspondence with
PartyEndpointMessageReceivedStateChanges. Multiple small
messages may be coalesced together into a single packet, or
a large message may be fragmented into multiple packets
depending on configuration and environmental factors.
Further, packets may be used to carry chat or other internal
library functionality (e.g., API operation support messages,
protocol acknowledgements or retries) on behalf of the
application without an explicit
PartyLocalEndpoint::SendMessage() call.

This statistic does not include any packets received as part of


HTTP web client operations that are used internally by the
Party library for some aspects of authentication,
management transactions, speech-to-text transcription, and
text-to-speech synthesis.

ReceivedProtocolBytes The total number of internal protocol bytes ever received


from remote devices as part of this network.

This statistic represents the total number of bytes in internal


protocol packets received by the local device for any network
reason. This size includes
PartyEndpointMessageReceivedStateChange payloads but
also their internal protocol overhead, as well as any chat or
other internal library functionality needed (e.g., API
operation support messages, protocol acknowledgements or
retries).

The reported value does not include the packet overhead for
Internet protocols (e.g., UDP, IP) or that of lower level media
over which the Party library internal protocol operates.

This statistic does not include the sizes of any packets


received as part of HTTP web client operations that are used
internally by the Party library for some aspects of
authentication, management transactions, speech-to-text
transcription, and text-to-speech synthesis.

CurrentlyQueuedSendMessages The number of messages currently queued by


PartyLocalEndpoint::SendMessage() but not yet transmitted
from all local endpoints to all remote endpoints in the
network.

For efficiency, only a single message is queued by


PartyLocalEndpoint::SendMessage() when sending to
multiple target endpoints at once via the transparent cloud
relay server. Such messages will only be counted a single
time rather than multiplied per target endpoint.
C O N STA N T DESC RIP T IO N

CurrentlyQueuedSendMessageBytes The number of bytes of data in messages currently queued


by PartyLocalEndpoint::SendMessage() but not yet
transmitted from all local endpoints to all remote endpoints
in the network.

For efficiency, only a single message is queued by


PartyLocalEndpoint::SendMessage() when sending to
multiple target endpoints at once via the transparent cloud
relay server. Such messages' bytes will only be counted a
single time rather than multiplied per target endpoint.

CurrentlyActiveSendMessages The number of PartyLocalEndpoint::SendMessage()


messages from all local endpoints to all remote endpoints in
the network that are currently being transmitted or still have
more local state changes to be processed.

A message is considered "active" as soon as its first byte has


been placed in a packet that is being transmitted. It remains
active until transmission completes and the local
PartyDataBuffersReturnedStateChange for it (if applicable)
has been returned to
PartyManager::FinishProcessingStateChanges().

For efficiency, only a single message is queued by


PartyLocalEndpoint::SendMessage() when sending to
multiple target endpoints at once via the transparent cloud
relay server. Such messages will only be counted a single
time rather than multiplied per target endpoint.

CurrentlyActiveSendMessageBytes The number of bytes of data in


PartyLocalEndpoint::SendMessage() messages from all local
endpoints to all remote endpoints in the network that are
currently being transmitted or still have more local state
changes to be processed.

A message is considered "active" as soon as its first byte has


been placed in a packet that is being transmitted. It remains
active until transmission completes and the local
PartyDataBuffersReturnedStateChange for it (if applicable)
has been returned to
PartyManager::FinishProcessingStateChanges().

For efficiency, only a single message is queued by


PartyLocalEndpoint::SendMessage() when sending to
multiple target endpoints at once via the transparent cloud
relay server. Such messages' bytes will only be counted a
single time rather than multiplied per target endpoint.
C O N STA N T DESC RIP T IO N

TimedOutSendMessages The total number of PartyLocalEndpoint::SendMessage()


messages from all local endpoints to all remote endpoints in
the network that were ever discarded for exceeding their
send queue timeouts without being transmitted.

A message's send queue timeout is specified using


PartySendMessageQueuingConfiguration::timeoutInMillseco
nds when calling PartyLocalEndpoint::SendMessage().

For efficiency, only a single message is queued by


PartyLocalEndpoint::SendMessage() when sending to
multiple target endpoints at once via the transparent cloud
relay server. Such messages will only be counted a single
time rather than multiplied per target endpoint.

TimedOutSendMessageBytes The total number of bytes of data in


PartyLocalEndpoint::SendMessage() messages from all local
endpoints to all remote endpoints in the network that were
ever discarded for exceeding their send queue timeouts
without being transmitted.

A message's send queue timeout is specified using


PartySendMessageQueuingConfiguration::timeoutInMillseco
nds when calling PartyLocalEndpoint::SendMessage().

For efficiency, only a single message is queued by


PartyLocalEndpoint::SendMessage() when sending to
multiple target endpoints at once via the transparent cloud
relay server. Such messages' bytes will only be counted a
single time rather than multiplied per target endpoint.

CanceledSendMessages The total number of PartyLocalEndpoint::SendMessage()


messages from all local endpoints to all remote endpoints in
the network that were ever canceled.

Messages are canceled before being transmitted by the


application calling PartyLocalEndpoint::CancelMessages()
with a matching filter expression.

For efficiency, only a single message is queued by


PartyLocalEndpoint::SendMessage() when sending to
multiple target endpoints at once via the transparent cloud
relay server. Such messages will only be counted a single
time rather than multiplied per target endpoint.

CanceledSendMessageBytes The total number of bytes of data in


PartyLocalEndpoint::SendMessage() messages from all local
endpoints to all remote endpoints in the network that were
ever canceled.

Messages are canceled before being transmitted by the


application calling PartyLocalEndpoint::CancelMessages()
with a matching filter expression.

For efficiency, only a single message is queued by


PartyLocalEndpoint::SendMessage() when sending to
multiple target endpoints at once via the transparent cloud
relay server. Such messages' bytes will only be counted a
single time rather than multiplied per target endpoint.
Requirements
Header : Party.h

See also
Party members
PartyEndpointStatistic
PartySendMessageOptions
PartyNetwork::GetNetworkStatistics
PartyLocalEndpoint::SendMessage
PartyLocalEndpoint::GetEndpointStatistics
PartyOption
5/24/2022 • 3 minutes to read • Edit Online

Additional options that can be set to fine-tune Party library functionality.

Syntax
enum class PartyOption : uint32_t
{
LocalUdpSocketBindAddress = 0,
LocalDeviceDirectPeerConnectivityOptionsMask = 1,
TextChatFilterLevel = 2,
}

Constants
C O N STA N T DESC RIP T IO N

LocalUdpSocketBindAddress An option used to configure how the Party library binds to a


UDP socket.

To override this option, call PartyManager::SetOption


passing null for the object parameter, this value for the
option parameter, and an optional pointer to a
PartyLocalUdpSocketBindAddressConfiguration structure for
the value.

To query this option, call PartyManager::GetOption passing


null for the object parameter, this value for the option
parameter, and a pointer to an output
PartyLocalUdpSocketBindAddressConfiguration structure for
the value.

It's safe and recommended to override or query for this


option prior to initializing the Party library. Overriding the
local UDP socket bind address configuration will take effect
the next time the Party library is initialized. It doesn't modify
any Party library socket binding that has already been
initialized. Similarly, querying retrieves the configuration that
will be used with the next Party library initialization, not the
value actively in use if already initialized.

LocalDeviceDirectPeerConnectivityOptionsMask An option for constraining the permitted direct peer


connectivity between the local device and other devices in
networks that allow attempting such connections.

When successfully authenticating an initial local user into a


network with a
PartyNetworkConfiguration::directPeerConnectivityOptions
field set to a value other than
PartyDirectPeerConnectivityOptions::None, or when a
remote device authenticates into such a network, direct peer
connectivity between this local device and the remote
device(s) in the network may be attempted. The flags
configured by this option can be used to further constrain
the specific types of remote devices that are permitted to
the specific types of remote devices that are permitted to
C O N STA N T
involve the local device in these attempts. All flags are
DESC RIP T IO N
evaluated using a bitwise AND operation. That is, a particular
flag is actually only in effect for a given network's pair of
devices if it's enabled in three places: the network's
PartyNetworkConfiguration structure, and both devices'
respective local mask options. Even if the Party network
permits direct peer connectivity of the relevant form, either
device can unilaterally opt out of the IP address disclosure
and direct connection attempts between them by not
enabling the flag when overriding this option.

Direct peer connectivity is supported for the Windows 10


and Microsoft Game Core versions of the library. On those
platforms, the default value for the local device mask when
not yet set is
PartyDirectPeerConnectivityOptions::AnyPlatformType |
PartyDirectPeerConnectivityOptions::AnyEntityLoginProvider
. This means that such devices don't restrict any direct peer
connectivity permitted by a network's
PartyNetworkConfiguration until explicitly overridden to be
less permissive. For all other versions of the library, the
default value for the local device mask is
PartyDirectPeerConnectivityOptions::None and cannot
be changed; attempting to change it via
PartyManager::SetOption will fail. This means that such
devices will never attempt direct peer connectivity.

To override this option, call PartyManager::SetOption


passing null for the object parameter, this value for the
option parameter, and a pointer to a
PartyDirectPeerConnectivityOptions variable containing all
desired option flags.

To query this option, call PartyManager::GetOption passing


null for the object parameter, this value for the option
parameter, and a pointer to a
PartyDirectPeerConnectivityOptions variable into which the
currently configured option flags should be written.

It's recommended to override or query this option when not


connected to any networks. The configured value takes
effect the next time this device authenticates an initial user
into a new network. It doesn't alter the settings already
being used to participate in any existing networks. Similarly,
querying retrieves the currently configured value that will be
used with future networks, and not the value used with
existing networks.

It's also safe to override or query for this option prior to


initializing the Party library.
C O N STA N T DESC RIP T IO N

TextChatFilterLevel An option for fine-tuning the level that chat text will be
filtered at.

This feature only applies to incoming chat text detected as


English. The filter level cannot be changed for other
languages.

The filter level will apply to incoming chat text for all local
chat controls on the client. Filtering must be enabled with
PartyLocalChatControl::SetTextChatOptions for at least one
local chat control for this to have an effect on the chat text.

To override this option, call PartyManager::SetOption


passing null for the object parameter, this value for the
option parameter, and a pointer to a PartyTextChatFilterLevel
variable containing the desired filter level.

To query this option, call PartyManager::GetOption passing


null for the object parameter, this value for the option
parameter, and a pointer to a PartyTextChatFilterLevel
variable into which the currently configured filter level should
be written.

It is safe to override or query for this option at any time.

Requirements
Header : Party.h

See also
Party members
PartyManager::SetOption
PartyManager::GetOption
PartyLocalUdpSocketBindAddressConfiguration
PartyNetworkConfiguration
PartyDirectPeerConnectivityOptions
PartySendMessageOptions
5/24/2022 • 7 minutes to read • Edit Online

Options for controlling how a message is sent.

Syntax
enum class PartySendMessageOptions : int32_t
{
Default = 0x0000,
GuaranteedDelivery = 0x0001,
BestEffortDelivery = 0x0000,
SequentialDelivery = 0x0002,
NonsequentialDelivery = 0x0000,
CopyDataBuffers = 0x0000,
DontCopyDataBuffers = 0x0004,
CoalesceOpportunistically = 0x0000,
AlwaysCoalesceUntilFlushed = 0x0008,
RequireTimelyAcknowledgement = 0x0000,
AllowLazyAcknowledgement = 0x0010,
}

Constants
C O N STA N T DESC RIP T IO N

Default Use the default PartySendMessageOptions.

The default options are BestEffortDelivery,


NonsequentialDelivery, CopyDataBuffers,
CoalesceOpportunistically, and
RequireTimelyAcknowledgement.

GuaranteedDelivery Ensure the message is delivered to all targets, retransmitting


if necessary.

This option flag guarantees the message will arrive at each


target endpoint, regardless of environmental packet loss,
unless the target endpoint is destroyed. Packet
transmissions will be retried as needed.

This option flag works well when sending important state


information that must always reach the destination or else
the target should be removed from the network. Use it with
message content that does not have redundancy or the
ability to be interpolated/extrapolated if it's lost, and is worth
the potential increased bandwidth usage should packet
retransmissions be needed.

Guaranteeing delivery by itself doesn't imply a guarantee of


a particular delivery order; use the SequentialDelivery option
flag to enforce ordering.
C O N STA N T DESC RIP T IO N

BestEffortDelivery Transmit the message best-effort and ignore any packet loss.

This option flag requests only a single attempt to transmit


the message. If environmental packet loss occurs, the
transmission will not be retried and the application should
be prepared to handle the message's absence.

This option flag works well for information that is constantly


being updated and doesn't require every update to arrive.
Use it with message content that already has redundancy or
the ability to be interpolated/extrapolated if it's lost and isn't
worth extra bandwidth to retransmit.

This is the default if the GuaranteedDelivery option flag is


not specified.

SequentialDelivery Deliver the message in order relative to other messages sent


from this local endpoint to the target endpoint that were
also sent sequentially.

SequentialDelivery doesn't provide any guarantees about


the ordering of messages sent from different local endpoints
and/or to different target endpoints. Each endpoint pairing
should be considered a separate sequence space.

No guarantees are made about the order of sequential


messages in relation to non-sequential messages.

This option flag works well for state information that should
reach the destination in a particular sequence, even if that
means slightly less network efficiency and possibly waiting a
bit longer to receive it if there is packet loss or reordering by
the environment.

Using SequentialDelivery with GuaranteedDelivery may


result in messages being queued on the target endpoint
while waiting for previously sent sequential messages to
arrive. This may result in a perceived increase in latency
when experiencing environmental packet loss or reordering,
but the target endpoint will always see every message, in
the same order in which they were sent.

Using SequentialDelivery with BestEffortDelivery may result


in messages being dropped if one arrives at the target
endpoint out of order and a later sequential message had
already been delivered. The target endpoint will always see
the sequence moving forward, but there may be gaps in
that sequence. An older message will never be delivered
after a newer one.
C O N STA N T DESC RIP T IO N

NonsequentialDelivery Deliver the message to targets as soon as it arrives.

Messages sent with the non-sequential delivery option do


not provide any guarantees about the order in which they
are delivered with respect to any other messages, sequential
or non-sequential. They will be delivered to the targets as
soon as they arrive, which may not be the same order in
which they were sent if there is packet loss or reordering by
the environment.

This option flag works well for messages that are safe to
process in any order or have their own inherent ordering
information already, and where you'd like maximum network
efficiency and lowest perceived latency.

This is the default if the SequentialDelivery option flag is not


specified.

CopyDataBuffers Instructs the Party library to make a copy of the supplied


data buffers for subsequent transmission.

The memory contents in the provided PartyDataBuffer


structures will be copied so the caller does not need to keep
the buffers around after PartyLocalEndpoint::SendMessage()
returns. This is more convenient but slightly less efficient
than using the DontCopyDataBuffers option flag.

This is the default if the DontCopyDataBuffers option flag is


not specified.

DontCopyDataBuffers Informs the Party library to use the supplied data buffers
directly and that the caller will keep the memory valid until
the library no longer needs them.

The memory referenced by the provided PartyDataBuffer


structures will not be copied but instead ownership will
temporarily be transferred to the Party library so the
memory can be accessed directly without additional copying
overhead during the transmission process. It's the caller's
responsibility to ensure the memory buffers remain valid
and unmodified until the library no longer needs them and
ownership is transferred back via a
PartyDataBuffersReturnedStateChange. This is more efficient
but can be less convenient than using the CopyDataBuffers
option.

The PartyDataBuffer structures themselves do not need to


remain valid after the PartyLocalEndpoint::SendMessage()
call returns, only the memory they reference.
C O N STA N T DESC RIP T IO N

CoalesceOpportunistically Specifies that this message should be coalesced with any


other queued messages but should not delay transmission if
there aren't any waiting.

Coalescing multiple messages together in a single packet


allows maximizing bandwidth efficiency (reducing per- packet
overhead) at the potential expense of perceived latency for a
message if you delay its transmission in order to coalesce.
Sending with this flag causes the Party library to coalesce
the message if there are other queued messages available,
but not to wait for more messages if none exist and this
message can be transmitted immediately.

Use this flag if you typically batch your network updates into
single, periodic messages that are not likely to be queued
around the same time as other messages and would not
gain bandwidth efficiency if delayed.

This flag does not guarantee that the message begins


transmitting immediately. If the connection quality or
receiver responsiveness do not appear to currently support
sending additional data yet, then the message may be
queued to await the next transmission opportunity.

This is the default if the AlwaysCoalesceUntilFlushed option


flag is not specified.

AlwaysCoalesceUntilFlushed Specifies that this message should always try to be coalesced


with other messages and expect a
PartyLocalEndpoint::FlushMessages() call to begin
transmitting.

Coalescing multiple messages together in a single packet


allows maximizing bandwidth efficiency (reducing per- packet
overhead) at the potential expense of perceived latency for a
message if you delay its transmission in order to coalesce.
Sending with this flag causes the Party library to always
prefer coalescing the message and delay transmission until
PartyLocalEndpoint::FlushMessages() is called.

Consider using this flag if you typically send a lot of small


messages to the same targets in the same update loop and
want to explicitly inform the Party library when the full
update loop iteration is complete.

Even with this flag there are scenarios where the message
might begin transmitting without requiring an explicit
PartyLocalEndpoint::FlushMessages() call. This can occur
when there are other queued messages that are already
being transmitted for other reasons and there is room in the
packet to include this message. Similarly, when enough
message data bytes exist to send a full packet and no more
coalescence is possible, the packet will be sent. Calling
PartyLocalEndpoint::FlushMessages() when all messages
have already begun transmitting is benign.
C O N STA N T DESC RIP T IO N

RequireTimelyAcknowledgement Indicates that this message should be acknowledged (if


needed) in a timely manner.

Receivers acknowledge reception of messages to inform the


sender of delivery success or failure so it can do things such
as retry dropped packets that contained messages sent with
the GuaranteedDelivery option flag. Acknowledgements are
often piggybacked on packets as part of typical bi-
directional communication, but if no packets are flowing in
the return direction, this flag instructs the target endpoints
to only wait a small, internally managed timeout for
piggybacking opportunities before forcing acknowledgement
packets to inform the sender. That dedicated packet
consumes some extra overhead but ensures the sender gets
timely status for issuing any necessary retries.

Using this flag for most guaranteed delivery messages is


recommended. It works well with messages that are latency
sensitive. It also works well when bi-directional guaranteed
delivery send patterns are infrequent or unpredictable.

This is the default if the AllowLazyAcknowledgement option


flag is not specified.

This flag is ignored if the GuaranteedDelivery option flag is


not specified.

AllowLazyAcknowledgement Indicates that this message can be acknowledged when


convenient rather than urgently.

Receivers acknowledge reception of messages to inform the


sender of delivery success or failure so it can do things such
as retry dropped packets that contained messages sent with
the GuaranteedDelivery option flag. Acknowledgements are
often piggybacked on packets as part of typical bi-
directional communication, but if no packets are flowing in
the return direction, this flag instructs the target endpoints
to wait for piggybacking opportunities without forcing
acknowledgement packets to inform the sender. This delays
the sender finding out status for any necessary retries, but
avoids extra overhead consumed by a dedicated packet.

Consider using this flag for guaranteed delivery messages


that are "fire-and-forget" and are not latency sensitive. It
may also reduce overhead when bi-directional send patterns
are frequent.

This flag is ignored if the GuaranteedDelivery option flag is


not also specified.

Requirements
Header : Party.h

See also
Party members
PartySendMessageQueuingConfiguration
PartyDataBuffersReturnedStateChange
PartyLocalEndpoint::SendMessage
PartyLocalEndpoint::FlushMessages
PartyStateChangeResult
5/24/2022 • 2 minutes to read • Edit Online

Results for operations that generate state changes.

Syntax
enum class PartyStateChangeResult
{
Succeeded = 0,
UnknownError = 1,
CanceledByTitle = 2,
InternetConnectivityError = 3,
PartyServiceError = 4,
NoServersAvailable = 5,
UserNotAuthorized = 6,
UserCreateNetworkThrottled = 7,
TitleNotEnabledForParty = 8,
NetworkLimitReached = 10,
NetworkNoLongerExists = 11,
VersionMismatch = 13,
LeaveNetworkCalled = 14,
FailedToBindToLocalUdpSocket = 15,
}

Constants
C O N STA N T DESC RIP T IO N

Succeeded The operation succeeded.

UnknownError An unknown error occurred.

CanceledByTitle Another title operation canceled this operation.

InternetConnectivityError The local device has internet connectivity issues which


caused the operation to fail.

PartyServiceError The operation failed because of an unexpected error in the


Party service.

NoServersAvailable There are no available transparent cloud relay servers in the


regions specified by the call to
PartyManager::CreateNewNetwork().

UserNotAuthorized The PartyLocalUser specified in the call to


PartyManager::CreateNewNetwork() or
PartyNetwork::AuthenticateLocalUser() is not authorized to
complete the operation.

UserCreateNetworkThrottled The PartyLocalUser specified in the call to


PartyManager::CreateNewNetwork() has created too many
networks and cannot create new networks at this time.
C O N STA N T DESC RIP T IO N

TitleNotEnabledForParty The title has not been enabled to use PlayFab Party. PlayFab
Party must be enabled in the PlayFab Game Manager.

NetworkLimitReached The network rejected this operation because it would violate


a limit in the network's configuration. See
PartyNetworkConfiguration.

NetworkNoLongerExists The network no longer exists.

VersionMismatch The operation failed because this version of the Party library
was incompatible with either the Party service or the Party
network.

LeaveNetworkCalled The network was gracefully exited by the local device.

FailedToBindToLocalUdpSocket The operation failed because the Party library was unable to
bind to the socket specified in the
PartyOption::LocalUdpSocketBindAddress option.

Requirements
Header : Party.h

See also
Party members
PartyStateChangeType
5/24/2022 • 6 minutes to read • Edit Online

The types of state changes that can occur.

Syntax
enum class PartyStateChangeType : uint32_t
{
RegionsChanged = 0,
DestroyLocalUserCompleted = 1,
CreateNewNetworkCompleted = 2,
ConnectToNetworkCompleted = 3,
AuthenticateLocalUserCompleted = 4,
NetworkConfigurationMadeAvailable = 5,
NetworkDescriptorChanged = 6,
LocalUserRemoved = 7,
RemoveLocalUserCompleted = 8,
CreateEndpointCompleted = 10,
DestroyEndpointCompleted = 11,
EndpointCreated = 12,
EndpointDestroyed = 13,
RemoteDeviceCreated = 14,
RemoteDeviceDestroyed = 15,
RemoteDeviceJoinedNetwork = 16,
RemoteDeviceLeftNetwork = 17,
LeaveNetworkCompleted = 19,
NetworkDestroyed = 20,
EndpointMessageReceived = 21,
DataBuffersReturned = 22,
CreateChatControlCompleted = 31,
DestroyChatControlCompleted = 32,
ChatControlCreated = 33,
ChatControlDestroyed = 34,
ChatTextReceived = 36,
VoiceChatTranscriptionReceived = 37,
SetChatAudioInputCompleted = 38,
SetChatAudioOutputCompleted = 39,
LocalChatAudioInputChanged = 40,
LocalChatAudioOutputChanged = 41,
SetTextToSpeechProfileCompleted = 42,
SynthesizeTextToSpeechCompleted = 43,
ChatControlJoinedNetwork = 46,
ChatControlLeftNetwork = 47,
ConnectChatControlCompleted = 48,
DisconnectChatControlCompleted = 49,
PopulateAvailableTextToSpeechProfilesCompleted = 50,
CreateInvitationCompleted = 51,
RevokeInvitationCompleted = 52,
InvitationCreated = 53,
InvitationDestroyed = 54,
SetTranscriptionOptionsCompleted = 56,
SetTextChatOptionsCompleted = 57,
ConfigureAudioManipulationVoiceStreamCompleted = 58,
ConfigureAudioManipulationCaptureStreamCompleted = 59,
ConfigureAudioManipulationRenderStreamCompleted = 60,
}

Constants
C O N STA N T DESC RIP T IO N

RegionsChanged The list of regions in which the title may create networks has
changed.

The PartyStateChange object should be cast to a


PartyRegionsChangedStateChange object for more
information.

DestroyLocalUserCompleted The operation started by a previous call to


PartyManager::DestroyLocalUser() completed.

The PartyStateChange object should be cast to a


PartyDestroyLocalUserCompletedStateChange object for
more information.

CreateNewNetworkCompleted The operation started by a previous call to


PartyManager::CreateNewNetwork() completed.

The PartyStateChange object should be cast to a


PartyCreateNewNetworkCompletedStateChange object for
more information.

ConnectToNetworkCompleted The operation started by a previous call to


PartyManager::ConnectToNetwork() completed.

The PartyStateChange object should be cast to a


PartyConnectToNetworkCompletedStateChange object for
more information.

AuthenticateLocalUserCompleted The operation started by a previous call to


PartyNetwork::AuthenticateLocalUser() completed.

The PartyStateChange object should be cast to a


PartyAuthenticateLocalUserCompletedStateChange object
for more information.

NetworkConfigurationMadeAvailable The network configuration associated with the PartyNetwork


is now available.

The PartyStateChange object should be cast to a


PartyNetworkConfigurationMadeAvailableStateChange
object for more information.

NetworkDescriptorChanged The network descriptor associated with the PartyNetwork


changed.

The PartyStateChange object should be cast to a


PartyNetworkDescriptorChangedStateChange object for
more information.

LocalUserRemoved A local user has been removed from the network by a


previous call to PartyNetwork::RemoveLocalUser() or
PartyManager::DestroyLocalUser().

The PartyStateChange object should be cast to a


PartyLocalUserRemovedStateChange object for more
information.
C O N STA N T DESC RIP T IO N

RemoveLocalUserCompleted The operation to remove a local user started by a previous


call to PartyNetwork::RemoveLocalUser() completed.

The PartyStateChange object should be cast to a


PartyRemoveLocalUserCompletedStateChange object for
more information.

CreateEndpointCompleted The operation started by a previous call to


PartyNetwork::CreateEndpoint() completed.

The PartyStateChange object should be cast to a


PartyCreateEndpointCompletedStateChange object for more
information.

DestroyEndpointCompleted The operation started by a previous call to


PartyNetwork::DestroyEndpoint() completed.

The PartyStateChange object should be cast to a


PartyDestroyEndpointCompletedStateChange object for
more information.

EndpointCreated A new endpoint was created.

The PartyStateChange object should be cast to a


PartyEndpointCreatedStateChange object for more
information.

EndpointDestroyed An endpoint was destroyed.

The PartyStateChange object should be cast to a


PartyEndpointDestroyedStateChange object for more
information.

RemoteDeviceCreated A new remote device was created.

The PartyStateChange object should be cast to a


PartyRemoteDeviceCreatedStateChange object for more
information.

RemoteDeviceDestroyed A remote device was destroyed.

The PartyStateChange object should be cast to a


PartyRemoteDeviceDestroyedStateChange object for more
information.

RemoteDeviceJoinedNetwork A remote device joined a network.

The PartyStateChange object should be cast to a


PartyRemoteDeviceJoinedNetworkStateChange object for
more information.

RemoteDeviceLeftNetwork A remote device left a network.

The PartyStateChange object should be cast to a


PartyRemoteDeviceLeftNetworkStateChange object for more
information.
C O N STA N T DESC RIP T IO N

LeaveNetworkCompleted The operation started by a previous call to


PartyNetwork::LeaveNetwork() completed.

The PartyStateChange object should be cast to a


PartyLeaveNetworkCompletedStateChange object for more
information.

NetworkDestroyed A network was destroyed.

The PartyStateChange object should be cast to a


PartyNetworkDestroyedStateChange object for more
information.

EndpointMessageReceived A data send was received from an endpoint.

The PartyStateChange object should be cast to a


PartyEndpointMessageReceivedStateChange object for more
information.

DataBuffersReturned The PartyDataBuffer set provided to SendMessage is no


longer in use by the library.

The PartyStateChange object should be cast to a


PartyDataBuffersReturnedStateChange object for more
information.

CreateChatControlCompleted The operation started by a previous call to


PartyLocalDevice::CreateChatControl() completed.

The PartyStateChange object should be cast to a


PartyCreateChatControlCompletedStateChange object for
more information.

DestroyChatControlCompleted The operation started by a previous call to


PartyLocalDevice::DestroyChatControl() completed.

The PartyStateChange object should be cast to a


PartyDestroyChatControlCompletedStateChange object for
more information.

ChatControlCreated A new PartyChatControl was created.

The PartyStateChange object should be cast to a


PartyChatControlCreatedStateChange object for more
information.

ChatControlDestroyed A PartyChatControl was destroyed.

The PartyStateChange object should be cast to a


PartyChatControlDestroyedStateChange object for more
information.

ChatTextReceived Chat text has been received.

The PartyStateChange object should be cast to a


PartyChatTextReceivedStateChange object for more
information.
C O N STA N T DESC RIP T IO N

VoiceChatTranscriptionReceived A voice chat transcription has been received.

The PartyStateChange object should be cast to a


PartyVoiceChatTranscriptionReceivedStateChange object for
more information.

SetChatAudioInputCompleted The operation started by a previous call to


PartyLocalChatControl::SetAudioInput() completed.

The PartyStateChange object should be cast to a


PartySetChatAudioInputCompletedStateChange object for
more information.

SetChatAudioOutputCompleted The operation started by a previous call to


PartyLocalChatControl::SetAudioOutput() completed.

The PartyStateChange object should be cast to a


PartySetChatAudioOutputCompletedStateChange object for
more information.

LocalChatAudioInputChanged The state of an audio input associated with a local chat


control changed.

The PartyStateChange object should be cast to a


PartyLocalChatAudioInputChangedStateChange object for
more information.

LocalChatAudioOutputChanged The state of an audio output associated with a local chat


control changed.

The PartyStateChange object should be cast to a


PartyLocalChatAudioOutputChangedStateChange object for
more information.

SetTextToSpeechProfileCompleted The operation started by a previous call to


PartyLocalChatControl::SetTextToSpeechProfile() completed.

The PartyStateChange object should be cast to a


PartySetTextToSpeechProfileCompletedStateChange object
for more information.

SynthesizeTextToSpeechCompleted The operation started by a previous call to


PartyLocalChatControl::SynthesizeTextToSpeech() completed.

The PartyStateChange object should be cast to a


PartySynthesizeTextToSpeechCompletedStateChange object
for more information. Receiving a state change of this type
indicates that the audio has been synthesized, not that the
audio has been transmitted to anyone.

ChatControlJoinedNetwork The chat control joined a network.

The PartyStateChange object should be cast to a


PartyChatControlJoinedNetworkStateChange object for
more information.
C O N STA N T DESC RIP T IO N

ChatControlLeftNetwork The chat control left a network.

The PartyStateChange object should be cast to a


PartyChatControlLeftNetworkStateChange object for more
information.

ConnectChatControlCompleted The operation started by a previous call to


PartyNetwork::ConnectChatControl() completed.

The PartyStateChange object should be cast to a


PartyConnectChatControlCompletedStateChange object for
more information.

DisconnectChatControlCompleted The operation started by a previous call to


PartyNetwork::DisconnectChatControl() completed.

The PartyStateChange object should be cast to a


PartyDisconnectChatControlCompletedStateChange object
for more information.

PopulateAvailableTextToSpeechProfilesCompleted The operation started by a previous call to


PartyLocalChatControl::PopulateAvailableTextToSpeechProfile
s() completed.

The PartyStateChange object should be cast to a


PartyPopulateAvailableTextToSpeechProfilesCompletedStateC
hange object for more information.

CreateInvitationCompleted The operation started by a previous call to


PartyNetwork::CreateInvitation() completed.

The PartyStateChange object should be cast to a


PartyCreateInvitationCompletedStateChange object for more
information.

RevokeInvitationCompleted The operation started by a previous call to


PartyNetwork::RevokeInvitation() completed.

The PartyStateChange object should be cast to a


PartyRevokeInvitationCompletedStateChange object for
more information.

InvitationCreated A new invitation was created.

The PartyStateChange object should be cast to a


PartyInvitationCreatedStateChange object for more
information.

InvitationDestroyed An invitation was destroyed.

The PartyStateChange object should be cast to a


PartyInvitationDestroyedStateChange object for more
information.
C O N STA N T DESC RIP T IO N

SetTranscriptionOptionsCompleted The operation started by a previous call to


PartyLocalChatControl::SetTranscriptionOptions() completed.

The PartyStateChange object should be cast to a


PartySetTranscriptionOptionsCompletedStateChange object
for more information.

SetTextChatOptionsCompleted The operation started by a previous call to


PartyLocalChatControl::SetTextChatOptions() completed.

The PartyStateChange object should be cast to a


PartySetTextChatOptionsCompletedStateChange object for
more information.

ConfigureAudioManipulationVoiceStreamCompleted The operation started by a previous call to


PartyChatControl::ConfigureAudioManipulationVoiceStream()
completed.

The PartyStateChange object should be cast to a


PartyConfigureAudioManipulationVoiceStreamCompletedSta
teChange object for more information.

ConfigureAudioManipulationCaptureStreamCompleted The operation started by a previous call to


PartyLocalChatControl::ConfigureAudioManipulationCapture
Stream() completed.

The PartyStateChange object should be cast to a


PartyConfigureAudioManipulationCaptureStreamCompleted
StateChange object for more information.

ConfigureAudioManipulationRenderStreamCompleted The operation started by a previous call to


PartyLocalChatControl::ConfigureAudioManipulationRenderS
tream() completed.

The PartyStateChange object should be cast to a


PartyConfigureAudioManipulationRenderStreamCompletedSt
ateChange object for more information.

Requirements
Header : Party.h

See also
Party members
PartySynthesizeTextToSpeechType
5/24/2022 • 2 minutes to read • Edit Online

Types of text-to-speech operations.

Syntax
enum class PartySynthesizeTextToSpeechType
{
Narration = 0,
VoiceChat = 1,
}

Constants
C O N STA N T DESC RIP T IO N

Narration The audio should be rendered to the local chat control's


audio output.

This type is typically used for the "narration" scenario where


text-to-speech audio is rendered to the local chat control for
arbitrary game-defined scenarios, such as the narration of
received text. It may also be used for the "voice auditioning"
scenario where a user compares audio between text-to-
speech profiles to select the profile they prefer to use in text-
to-speech voice chat scenarios. The chat control does not
need to be in a network for this functionality.

The audio will never be transcribed, even if transcription is


enabled.

VoiceChat The audio should be rendered to the chat controls to which


the local chat control is configured to send audio.

This type is typically used for the "text-to-speech voice chat"


scenario where a user elects not to participate in voice chat
with their microphone, but still wishes to participate in the
voice chat via text-to-speech audio. The audio will be
rendered to the chat controls to which the local chat control
has been configured to send audio via
PartyLocalChatControl::SetPermissions(). The chat control
does not need to be in a network for a text-to-speech
operation of this type to succeed, but it will have no
apparent effect because there will be no other chat controls
to which the local chat control could be configured to send
audio.

Because the audio represents the user's voice, it will be


transcribed according to the options specified via
PartyLocalChatControl::SetTranscriptionOptions().

Requirements
Header : Party.h

See also
Party members
PartyLocalChatControl::SetTextToSpeechProfile
PartyLocalChatControl::GetTextToSpeechProfile
PartyLocalChatControl::SynthesizeTextToSpeech
PartyTextChatFilterLevel
5/24/2022 • 2 minutes to read • Edit Online

The level of filtering that will apply to incoming text chat when text moderation is enabled with
PartyLocalChatControl::SetTextChatOptions.

Syntax
enum class PartyTextChatFilterLevel : uint32_t
{
FamilyFriendly = 0,
Medium = 1,
Mature = 2,
}

Constants
C O N STA N T DESC RIP T IO N

FamilyFriendly Text chat will be filtered at a family-friendly level.

Medium Text chat will be filtered at a medium level.

Mature Text chat will be filtered at a mature level.

Requirements
Header : Party.h

See also
Party members
PartyManager::SetOption
PartyLocalChatControl::SetTextChatOptions
PartyTextChatOptions
5/24/2022 • 2 minutes to read • Edit Online

Text chat options.

Syntax
enum class PartyTextChatOptions
{
None = 0x0,
TranslateToLocalLanguage = 0x1,
FilterOffensiveText = 0x2,
}

Constants
C O N STA N T DESC RIP T IO N

None No options are selected.

TranslateToLocalLanguage Incoming text chat will be translated to the local chat


control's language.

The language specified via


PartyLocalChatControl::GetLanguage() is the language to
which the incoming text chat will be translated. The
translations will be provided in addition to the original text
chat via a PartyChatTextReceivedStateChange.

If translation is enabled, a translation corresponding to the


local chat control's language will always be provided in each
resulting PartyChatTextReceivedStateChange. If the source
chat control's language is the same as the local chat control's
language, the chat text and translation strings will be
identical.

FilterOffensiveText Offensive terms will be filtered out of incoming text chat.

For incoming chat text detected as English, the filtering level


may be adjusted using the PartyOption::TextChatFilterLevel
option in PartyManager::SetOption(). The default level is
family-friendly.

Requirements
Header : Party.h

See also
Party members
PartyLocalChatControl::SetTextChatOptions
PartyLocalChatControl::GetLanguage
PartyChatTextReceivedStateChange
PartyThreadId
5/24/2022 • 2 minutes to read • Edit Online

High-level categorization of internal processing tasks.

Syntax
enum class PartyThreadId
{
Audio = 0,
Networking = 1,
}

Constants
C O N STA N T DESC RIP T IO N

Audio Represents the internal processing task related to audio.

Networking Represents the internal processing task related to


networking.

Remarks
When used with PartyManager::GetWorkMode() and PartyManager::SetWorkMode(), allows the title to read and
write (respectively) the work mode for the associated internal processing task. Title interaction with the internal
processing task differs greatly depending on the currently-configured work mode.

When the work mode of the processing task associated with PartyThreadId::Audio is set to
PartyWorkMode::Automatic, the task is performed by the Party library using internally-managed, high priority,
frequently-running threads with real-time requirements. On Windows and Xbox consoles, these audio threads
interact directly with XAudio2 every 40 milliseconds. The Party library's instance(s) of XAudio2 will be initialized
with a processor affinity that corresponds to the processor affinity configured for the audio thread type via
PartyManager::SetThreadAffinityMask(). If no processor affinity is specified for the audio thread type, the
instance(s) of XAudio2 will be initialized with a processor affinity of XAUDIO2_DEFAULT_PROCESSOR.

Similarly, when the work mode of the processing task associated with PartyThreadId::Networking is set to
PartyWorkMode::Automatic, networking threads are created and managed internally. These threads are driven
from both network I/O and polling mechanisms, waking every 50 to 100 milliseconds or whenever network
traffic is received.

For all processing tasks, when the work mode is set to PartyWorkMode::Automatic, title
interaction/responsibility is limited to specifying the processor affinity of associated internal worker threads via
PartyManager::SetThreadAffinityMask(). Alternatively, when a processing task's work mode is set to
PartyWorkMode::Manual, internal worker threads are no longer created and managed by the Party library.
Instead, it becomes the title's responsibility to perform the required processing via periodic calls to
PartyManager::DoWork(). The periodicity of these calls should match that of the internal threads that are created
when the work mode is PartyWorkMode::Automatic.
Requirements
Header : Party.h

See also
Party members
PartyManager::GetThreadAffinityMask
PartyManager::SetThreadAffinityMask
PartyManager::SetWorkMode
PartyManager::GetWorkMode
PartyManager::DoWork
PartyTranslationReceivedOptions
5/24/2022 • 2 minutes to read • Edit Online

Flags describing how a translation was received.

Syntax
enum class PartyTranslationReceivedOptions
{
None = 0x0,
Truncated = 0x1,
}

Constants
C O N STA N T DESC RIP T IO N

None There is no additional translation information.

Truncated The translation was truncated.

A translation string may be up to


c_maxChatTextMessageLength characters long, not
including the null terminator. Truncation occurs if the
translated string length would exceed that limit, which can
happen due to language differences even though the
original string length is less than or equal to
c_maxChatTextMessageLength . Truncation may occur at an
arbitrary point in the UTF-8 byte sequence and may not
result in a complete, valid character or word. Strings are
always null terminated, even when truncated.

Requirements
Header : Party.h

See also
Party members
PartyVoiceChatTranscriptionOptions
5/24/2022 • 2 minutes to read • Edit Online

Voice chat transcription options.

Syntax
enum class PartyVoiceChatTranscriptionOptions
{
None = 0x0,
TranscribeSelf = 0x1,
TranscribeOtherChatControlsWithMatchingLanguages = 0x2,
TranscribeOtherChatControlsWithNonMatchingLanguages = 0x4,
TranslateToLocalLanguage = 0x10,
DisableProfanityMasking = 0x20,
TranscribeSelfRegardlessOfNetworkState = 0x40,
}

Constants
C O N STA N T DESC RIP T IO N

None No chat controls will be transcribed.

TranscribeSelf Transcriptions of the local chat control will be generated and


provided to the same local chat control via
PartyVoiceChatTranscriptionReceivedStateChange events
while in a network with at least one other chat control.

TranscribeOtherChatControlsWithMatchingLanguages Transcriptions of other chat controls with the same language


as the local chat control will be generated and provided to
the local chat control via
PartyVoiceChatTranscriptionReceivedStateChange events.

TranscribeOtherChatControlsWithNonMatchingLanguages Transcriptions of other chat controls with languages that are


different from the local chat control's language will be
generated and provided to the local chat control via
PartyVoiceChatTranscriptionReceivedStateChange events.

The transcriptions are not translated by default. Translation


to the local chat control's language can also be enabled by
adding TranslateToLocalLanguage.
C O N STA N T DESC RIP T IO N

TranslateToLocalLanguage Transcriptions will be translated to the local chat control's


language.

Transcriptions generated as specified via other


PartyVoiceChatTranscriptionOptions values will be translated
into the local chat control's language, which is specified by
PartyLocalChatControl::GetLanguage(). The translations will
be provided in addition to the original transcription via
PartyVoiceChatTranscriptionReceivedStateChange events.

If translation is enabled, a translation corresponding to the


local chat control's language will always be provided in each
resulting PartyVoiceChatTranscriptionReceivedStateChange. If
the speaking chat control's language is the same as the local
chat control's language, the transcription and translation
strings will be identical.

This option will have no effect unless also combined with one
or more of TranscribeSelf,
TranscribeOtherChatControlsWithMatchingLanguages, and
TranscribeOtherChatControlsWithNonMatchingLanguages.

DisableProfanityMasking Transcriptions will be provided without masking profanity.

By default, profanity is masked by replacing each character


with an asterisk. For instance, a 4-letter profanity is replaced
with "****". When this option is enabled, no masking will be
applied to profanity; the raw text will be provided.

TranscribeSelfRegardlessOfNetworkState Transcriptions of the local chat control will be generated and


provided to the same local chat control via
PartyVoiceChatTranscriptionReceivedStateChange regardless
of whether the chat control is in a network with any other
chat controls.

This option overrides TranscribeSelf. This option is provided


for backwards compatibility and typically should not be used.

Requirements
Header : Party.h

See also
Party members
PartyLocalChatControl::SetTranscriptionOptions
PartyVoiceChatTranscriptionReceivedStateChange
PartyVoiceChatTranscriptionPhraseType
PartyVoiceChatTranscriptionPhraseType
5/24/2022 • 2 minutes to read • Edit Online

Types of transcription phrases.

Syntax
enum class PartyVoiceChatTranscriptionPhraseType
{
Hypothesis = 0,
Final = 1,
}

Constants
C O N STA N T DESC RIP T IO N

Hypothesis The transcription is a hypothesis phrase.

Final The transcription is a final phrase.

Remarks
A Hypothesis phrase represents a snapshot into the transcription process and does not represent a stable
accumulation of transcription. For example, a first speech hypothesis may contain the words "fine fun" and the
second hypothesis may contain the words "find funny". Hypothesis messages are frequent and there can be
many hypothesis messages associated with a particular phrase. Once a transcription of type Final is received, no
more hypothesis messages associated with that phrase will be provided; new hypothesis phrases will represent
a new logical phrase. Because each phrase is tied to a speaker, hypothesis messages for a phrase can be
correlated by inspecting the speaker field of the PartyVoiceChatTranscriptionReceivedStateChange.

Hypothesis phrases can optionally be used to improve the user experience by improving perceived
responsiveness. An example implementation might have a special text box for hypothesis messages that is
frequently updated with the latest hypothesis transcription from each chat control. Once a non-hypothesis
transcription is received, the transcription for the chat control would be removed from the hypothesis text box
and rendered in a long-lived text box.

A Final phrase represents the end of the transcription process after the speaker has completed a sentence or
phrase. Capitalization, punctuation, inverse text normalization, and profanity masking will have been applied to
this transcription. For example, if a user speaks a phrase represented by the words "my flight to seattle leaves at
six", the transcription will read "My flight to Seattle leaves at 6." Inverse text normalization is the process that
converts the word "six" to the number "6". Profane words will be replaced by asterisks.

If the associated transcription represents the audio generated by a call to


PartyLocalChatControl::SynthesizeTextToSpeech(), the transcription will match the text string used to generate
the audio. No post-processing, such as capitalization and punctuation, will be applied to the text.
Requirements
Header : Party.h

See also
Party members
PartyLocalChatControl::SynthesizeTextToSpeech
PartyVoiceChatTranscriptionReceivedStateChange
PartyWorkMode
5/24/2022 • 2 minutes to read • Edit Online

Configuration modes representing how the Party library will manage an internal processing task.

Syntax
enum class PartyWorkMode
{
Automatic = 0,
Manual = 1,
}

Constants
C O N STA N T DESC RIP T IO N

Automatic The Party library will create internal threads to automatically


handle the associated processing task.

This is the default, recommended option which encodes the


Party library's best practices for processing its internal task.

Manual The Party library will not create internal threads to handle
the associated processing task, instead relying on the title to
perform the task through calls to PartyManager::DoWork().

Remarks
For an overview of the processing tasks and their frequencies, see PartyThreadId.

Requirements
Header : Party.h

See also
Party members
PartyManager::SetWorkMode
PartyManager::GetWorkMode
PartyManager::DoWork
PlayFab Party Typedefs
5/24/2022 • 2 minutes to read • Edit Online

The PlayFab Party library uses several typedefs for convenient declarations of arrays of core types. It also
provides typedefs for a few basic types to add semantic meaning and aid in static analysis. Macros are provided
for dealing with PartyError return codes.

Basic types
PartyBool
The size of a C++ bool is implementation defined. PartyBool provides safe cross-platform serialization of
boolean values.

typedef uint8_t PartyBool;

PartyError
Error codes are 32-bit unsigned integers returned as PartyError . The success code is defined, as are macros for
determining if a error code represents success or failure.

typedef _Return_type_success_(return == c_partyErrorSuccess) uint32_t PartyError;


static const PartyError c_partyErrorSuccess = 0;

#define PARTY_SUCCEEDED(partyError) ((partyError) == c_partyErrorSuccess)


#define PARTY_FAILED(partyError) (!PARTY_SUCCEEDED((partyError)))

PartyString
A PartyString is a UTF-8 null-terminated const char array. The typedef exists in order to add an annotation for
static analysis.

typedef _Null_terminated_ const char * PartyString;

Arrays
A number of structs and method parameters use constant arrays of core types. To simplify usage and
declaration of these arrays, the following typedefs are provided.

typedef class PartyEndpoint * const * PartyEndpointArray;


typedef class PartyLocalEndpoint * const * PartyLocalEndpointArray;
typedef class PartyDevice * const * PartyDeviceArray;
typedef class PartyInvitation * const * PartyInvitationArray;
typedef class PartyNetwork * const * PartyNetworkArray;
typedef class PartyChatControl * const * PartyChatControlArray;
typedef class PartyLocalChatControl * const * PartyLocalChatControlArray;
typedef class PartyTextToSpeechProfile * const * PartyTextToSpeechProfileArray;
typedef const struct PartyStateChange * const * PartyStateChangeArray;
typedef class PartyLocalUser * const * PartyLocalUserArray;
T Y P EDEF C O RE T Y P E

PartyEndpointArray PartyEndpoint

PartyLocalEndpointArray PartyLocalEndpoint

PartyDeviceArray PartyDevice

PartyInvitationArray PartyInvitation

PartyNetworkArray PartyNetwork

PartyChatControlArray PartyChatControl

PartyLocalChatControlArray PartyLocalChatControl

PartyTextToSpeechProfileArray PartyTextToSpeechProfile

PartyStateChangeArray PartyStateChange

PartyLocalUserArray PartyLocalUser

Requirements
Header : Party.h

See also
Party members
PlayFab Party Unity SDK
5/24/2022 • 2 minutes to read • Edit Online

Classes
NAME DESC RIP T IO N

PlayFabLocalPlayer

PlayFabMultiplayerManager

PlayFabPlayer

Enums
NAME DESC RIP T IO N

AccessibilityMode Options that specify which accessibility settings are enabled.

ChatMessageType The type of delivery guarantee for a message.

ChatState The visual state of the player for rendering in the game's UI.

DeliveryOption The type of delivery guarantee for a message.

DirectPeerConnectivityOptions Flags controlling the attempted use of direct peer-to-peer


connectivity among devices in a network.

LogLevelType The amount of logging that is enabled.

PlayFabMultiplayerManagerErrorType The types of errors PlayFabMultiplayerManager can raise.

PlayFabMultiplayerManagerState The possible states that PlayFabMultiplayerManager can be


in.
Class PlayFabLocalPlayer
5/24/2022 • 2 minutes to read • Edit Online

Properties
NAME DESC RIP T IO N

IsChatControlAvailable Gets the indication whether any public API that relies on a
chat control associated with this player can be safely used.
Player's chat control becomes available after the user creates
or joins a party.

LanguageCode Gets or sets the language code for the player.

PlatformSpecificUserId Gets an additional identifier that represents the platform's


user-specific identifier.
IsChatControlAvailable
5/24/2022 • 2 minutes to read • Edit Online

Gets the indication whether any public API that relies on a chat control associated with this player can be safely
used. Player's chat control becomes available after the user creates or joins a party.

public bool PlayFabLocalPlayer.IsChatControlAvailable { get; }

Property Value
IsChatControlAvailable
bool
LanguageCode
5/24/2022 • 2 minutes to read • Edit Online

Gets or sets the language code for the player.


Currently, setting the language will only have effect before creating or joining a Party network.

public string PlayFabLocalPlayer.LanguageCode { get; set; }

Property Value
LanguageCode
string
The BCP 47 language code associated with the player.
PlatformSpecificUserId
5/24/2022 • 2 minutes to read • Edit Online

Gets an additional identifier that represents the platform's user-specific identifier.

public string PlayFabLocalPlayer.PlatformSpecificUserId { get; }

Property Value
PlatformSpecificUserId
string
Class PlayFabPlayer
5/24/2022 • 2 minutes to read • Edit Online

Properties
NAME DESC RIP T IO N

ChatState Gets the visual chat state of this player for display in your
game UI.

EntityKey Gets the EntityKey of the player.

IsLocal Returns true if this player is the local player, and false if this
player is a remote player.

IsMuted Gets or sets whether the player is muted.

VoiceLevel Gets or sets the volume of the player. The value is a float
between 0 and 1.
ChatState
5/24/2022 • 2 minutes to read • Edit Online

Gets the visual chat state of this player for display in your game's UI.

public ChatState PlayFabPlayer.ChatState { get; }

Property Value
ChatState
PlayFabPlayer.EntityKey
5/24/2022 • 2 minutes to read • Edit Online

Gets the EntityKey of the player.

public EntityKey PlayFabPlayer.EntityKey { get; }

Property Value
EntityKey
IsLocal
5/24/2022 • 2 minutes to read • Edit Online

Returns true if this player is the local player, and false if this player is a remote player.

public bool PlayFabPlayer.IsLocal { get; }

Property Value
IsLocal
bool
IsMuted
5/24/2022 • 2 minutes to read • Edit Online

Gets or sets whether the player is muted.

public bool PlayFabPlayer.IsMuted { get; set; }

Property Value
IsMuted
bool
VoiceLevel
5/24/2022 • 2 minutes to read • Edit Online

Gets or sets the volume of the player. The value is a float between 0 and 1.

public float PlayFabPlayer.VoiceLevel { get; set; }

Property Value
VoiceLevel
float
A value from zero to one inclusive.
Class PlayFabMultiplayerManager
5/24/2022 • 2 minutes to read • Edit Online

Properties
NAME DESC RIP T IO N

LocalPlayer Gets the local player for this client.

LogLevel Gets and sets the amount of logging currently enabled.

NetworkId Returns NetworkID of the current network to which the


player is connected. The other players can use this string to
join the network.

RemotePlayers Gets the collection of remote players currently joined to the


network.

SpeechToTextMode Gets or sets whether speech-to-text is enabled.

State Gets the current state of the multiplayer manager.

TextToSpeechMode Gets or sets whether text-to-speech is enabled.

TranslateChat Gets or sets whether incoming chat messages should be


translated to local player's language.

Methods
NAME DESC RIP T IO N

SendChatMessage Sends a chat message to a specific list of players (recipients).

SendChatMessageToAllPlayers Broadcasts a text message to all players. This API sends a


message such that it is guaranteed to arrive and in
sequential order.

CreateAndJoinNetwork Creates a network for players to join. After the player joins
the network, they can send the other players that are on the
network chat and data messages.

Get Returns a reference to the PlayFabMultiplayerManager


singleton instance.

JoinNetwork Joins this player to the specified network.

LeaveNetwork Causes the local player to leave the network.


NAME DESC RIP T IO N

SendDataMessage Sends a data message to the specified players using the


specified delivery options. The most advanced method for
sending data messages, allowing the developer more control
over how the message is sent.

SendDataMessageToAllPlayers Broadcasts a data message to all players.

UpdateEntityToken Updates the Entity token for the current local user.

Events
NAME DESC RIP T IO N

OnChatMessageReceived Occurs when a chat message is received.

OnDataMessageReceived Occurs when a data message is received.

OnDataMessageNoCopyReceived Occurs when a data message is received.

OnErrorEventHandler Occurs when there is an error.

OnNetworkChanged Occurs when the Network changes. When this event fires
you must move all the players to the new network, specified
in the newNetworkID so the players can continue to
communicate.

OnNetworkJoined Occurs when the local player joins the network.

OnNetworkLeft Occurs when the local player leaves the network.

OnRemotePlayerJoined Occurs when a remote player joins the network.

OnRemotePlayerLeft Occurs when a remote player leaves the network.


LocalPlayer
5/24/2022 • 2 minutes to read • Edit Online

Gets the local player for this client.

public PlayFabLocalPlayer PlayFabMultiplayerManager.LocalPlayer { get; }

Property Value
LocalPlayer
PlayFabLocalPlayer
LogLevel
5/24/2022 • 2 minutes to read • Edit Online

Gets or sets the amount of logging currently enabled.

public LogLevelType PlayFabMultiplayerManager.LogLevel { gets; sets; }

Property Value
LogLevel
LogLevelType
NetworkId
5/24/2022 • 2 minutes to read • Edit Online

Returns NetworkID of the current network to which the player is connected. The other players can use this string
to join the network. The NetworkId is populated when the OnNetworkJoined event fires. The NetworkId is cleared
when the OnNetworkLeft event fires.

public string PlayFabMultiplayerManager.NetworkId { get; }

Property Value
NetworkId
string

Remarks
The NetworkID , is an opaque serialized network descriptor string generated by the PlayFab Party library that
enables each PlayFab Party Unity client to connect to a Party network after one has been created. This string will
never contain non-ASCII characters, control characters, or other characters that would require JSON or XML
escaping.
RemotePlayers
5/24/2022 • 2 minutes to read • Edit Online

Gets the collection of remote players currently joined to the network.

public IList<PlayFabPlayer> PlayFabMultiplayerManager.RemotePlayers { get; }

Property Value
RemotePlayers
IList<T>
SpeechToTextMode
5/24/2022 • 2 minutes to read • Edit Online

Gets or sets whether speech-to-text is enabled.


Setting this property will have effect only when the local player created or joined a party.

public AccessibilityMode PlayFabMultiplayerManager.SpeechToTextMode { get; set; }

Property Value
SpeechToTextMode
AccessibilityMode
State
5/24/2022 • 2 minutes to read • Edit Online

Gets the current state of the multiplayer manager.

public PlayFabMultiplayerManagerState PlayFabMultiplayerManager.State { get; }

Property Value
State
PlayFabMultiplayerManagerState
TextToSpeechMode
5/24/2022 • 2 minutes to read • Edit Online

Gets or sets whether text-to-speech is enabled.


Note: if set to PlatformDefault , text-to-speech will only be enabled if local player's text-to-speech preferences
are enabled.

public AccessibilityMode PlayFabMultiplayerManager.TextToSpeechMode { get; set; }

Property Value
TextToSpeechMode
AccessibilityMode
TranslateChat
5/24/2022 • 2 minutes to read • Edit Online

Gets or sets whether incoming chat messages should be translated to local player's language.
Setting this property will have effect only when local player created or joined a party.

public bool PlayFabMultiplayerManager.TranslateChat { get; set; }

Property Value
TranslateChat
bool
SendChatMessage
5/24/2022 • 2 minutes to read • Edit Online

Sends a chat message to a specific list of players (recipients).

Syntax
public void PlayFabMultiplayerManager.Get().SendChatMessage(string message, IEnumerable<PlayFabPlayer>
recipients, DeliveryOption TBD);

Parameters
message string
The contents of the chat message.
recipients IEnumerable<PlayFabPlayer>
The recipients of the chat message.
TBD DeliveryOption

Remarks
PlayFabMultiplayerManager playFabMultiplayerManager = PlayFabMultiplayerManager.Get();
PlayFabMultiplayerManager.Get().SendChatMessage("Hello", targetPlayers, DeliveryOption.Guaranteed);

Return value
None.
SendChatMessageToAllPlayers
5/24/2022 • 2 minutes to read • Edit Online

Broadcasts a text message to all players. This API sends a message such that it is guaranteed to arrive and in
sequential order.

Syntax
public void PlayFabMultiplayerManager.Get().SendChatMessageToAllPlayers(string message);

Parameters
message string
The contents of the chat message.

Remarks
PlayFabMultiplayerManager playFabMultiplayerManager = PlayFabMultiplayerManager.Get();
playFabMultiplayerManager.SendChatMessageToAllPlayers("Hello");

Return value
None.
CreateAndJoinNetwork
5/24/2022 • 2 minutes to read • Edit Online

Creates a network for players to join. After the player joins the network, they can send the other players that are
on the network chat and data messages.

Syntax
public void PlayFabMultiplayerManager.Get().CreateAndJoinNetwork();

Parameters
None.
Return value
None.
Get
5/24/2022 • 2 minutes to read • Edit Online

Returns a reference to the PlayFabMultiplayerManager singleton instance.

Syntax
public static PlayFabMultiplayerManager Get()

Parameters
None.

PlayFabMultiplayerManager playFabMultiplayerManager = PlayFabMultiplayerManager.Get();

Return value
PlayFabMultiplayerManager
Returns the singleton instance of the PlayFabMultiplayerManager.
LeaveNetwork
5/24/2022 • 2 minutes to read • Edit Online

Causes the local player to leave the network.

Syntax
public void PlayFabMultiplayerManager.Get().LeaveNetwork();

Parameters
None.
Return value
None.
SendDataMessage
5/24/2022 • 2 minutes to read • Edit Online

SendDataMessage(buffer, recipients, deliveryOption);


Sends a data message to the specified players. This is a more advanced overload for sending data messages,
allowing the developer more control over how the message is sent.

Syntax
public void PlayFabMultiplayerManager.Get().SendDataMessage(byte[] buffer, IEnumerable<PlayFabPlayer>
recipients, DeliveryOption deliveryOption);

Parameters
Parameters
buffer IntPtr
A pointer to the buffer containing the data to send.
recipients IEnumerable<PlayFabPlayer>
The players to send the data message to. If the collection of players is empty, the data message will be broadcast
to all players.
deliver yOption DeliveryOption
Options specifying how to deliver the message.
Return value
None.

SendDataMessage(buffer, bufferSize, recipients, deliveryOption);


Sends a data message to the specified players using the specified delivery options. The most advanced method
for sending data messages, allowing the developer more control over how the message is sent.
Syntax

public void PlayFabMultiplayerManager.Get().SendDataMessage(byte[] buffer, IEnumerable<PlayFabPlayer>


recipients, DeliveryOption deliveryOption);

Parameters
buffer IntPtr
A pointer to the buffer containing the data to send.
bufferSize uint
The size of the buffer.
recipients IEnumerable<PlayFabPlayer>
The players to send the data message to. If the collection of players is empty, the data message will be broadcast
to all players.
deliver yOption DeliveryOption
Options specifying how to deliver the message.

Sample
...
byte[] buffer = Encoding.ASCII.GetBytes("Hello");
IntPtr unmanagedPointer = Marshal.AllocHGlobal(buffer.Length);
Marshal.Copy(buffer, 0, unmanagedPointer, buffer.Length);
PlayFabMultiplayerManager.Get().SendDataMessage(unmanagedPointer, (uint)buffer.Length, remotePlayers,
DeliveryOption.Guaranteed);
Marshal.FreeHGlobal(unmanagedPointer);
...

Return value
None.
SendDataMessageToAllPlayers
5/24/2022 • 2 minutes to read • Edit Online

Broadcasts a data message to all players.

Syntax
public void PlayFabMultiplayerManager.Get().SendDataMessageToAllPlayers(buffer);

Parameters
buffer byte[]
A buffer that contains the data to send.

Return value
None.
UpdateEntityToken
5/24/2022 • 2 minutes to read • Edit Online

Updates the Entity token for the current local user.

Syntax
public void PlayFabMultiplayerManager.Get().UpdateEntityToken(entityToken);

Parameters
entityToken string
The Entity token associated with the local user.

Return value
None.
OnChatMessageReceived
5/24/2022 • 2 minutes to read • Edit Online

Occurs when a chat message is received.

Arguments
sender (object)
The class that raised the event.
from (PlayFabPlayer)
The player the message was sent from.
message (string)
The contents of the message.
type (ChatMessageType )
A parameter that specifies the type of message.
OnDataMessageReceived
5/24/2022 • 2 minutes to read • Edit Online

Occurs when a data message is received.

Arguments
sender (object)
The class that raised the event.
from (PlayFabPlayer)
The player who sent the message.
buffer (byte [])
The data contents of the message.
OnDataMessageNoCopyReceived
5/24/2022 • 2 minutes to read • Edit Online

Occurs when a data message is received.

Arguments
sender (object)
The class that raised the event.
from (PlayFabPlayer)
The player who sent the message.
buffer (IntPtr)
The data contents of the message.
OnErrorEventHandler
5/24/2022 • 2 minutes to read • Edit Online

Occurs when there is an error.

Arguments
sender (object)
The class that raised the event.
args (PlayFabMultiplayerManagerErrorArgs)
An object that contains the details of the error.
OnNetworkChanged
5/24/2022 • 2 minutes to read • Edit Online

Occurs when the Network changes. When this event fires you must move all the players to the new network,
specified in the newNetworkID so the players can continue to communicate.

Arguments
sender (object)
The class that raised the event.
newNetworkId (string)
The identifier for the new network.
OnNetworkJoined
5/24/2022 • 2 minutes to read • Edit Online

Occurs when the local player joins the network.

Arguments
sender (object)
The class that raised the event.
networkId (string)
A string that identifies the network. Give this string to other players to allow them to connect to the network.
OnNetworkLeft
5/24/2022 • 2 minutes to read • Edit Online

Occurs when the local player leaves the network.

Arguments
sender (object)
The class that raised the event.
networkId (string)
A string that identifies the network.
OnRemotePlayerJoined
5/24/2022 • 2 minutes to read • Edit Online

Occurs when a remote player joins the network.

Arguments
sender (object)
The class that raised the event.
player (PlayFabPlayer)
The remote player who joined the network.
OnRemotePlayerLeft
5/24/2022 • 2 minutes to read • Edit Online

Occurs when a remote player leaves the network.

Arguments
sender (object)
The class that raised the event.
player (PlayFabPlayer)
The player who left the network.
AccessibilityMode
5/24/2022 • 2 minutes to read • Edit Online

Options that specify which accessibility settings are enabled.

Syntax
public enum AccessibilityMode
{
None,
PlatformDefault,
Enabled
}

Constants
C O N STA N T DESC RIP T IO N

None No accessibility settings are enabled.

PlatformDefault The accessibility settings are enabled based on the user


and/or platform's settings.

Enabled The accessibility settings are always enabled.


ChatMessageType
5/24/2022 • 2 minutes to read • Edit Online

The type of a chat message.

Syntax
public enum ChatMessageType
{
Text,
SpeechToText,
TextToSpeech
}

Constants
C O N STA N T DESC RIP T IO N

Text The standard type of text chat message.

SpeechToText A chat message that was transcribed into text, using speech-
to-text technology.

TextToSpeech An audio chat message that was synthesized, using text-to-


speech technology.
ChatMessageState
5/24/2022 • 2 minutes to read • Edit Online

The visual state of the player for rendering in the game's UI.

Syntax
public enum ChatState
{
NoAudioInput,
Muted,
MutedByPlatform,
Silent,
Talking
}

Constants
C O N STA N T DESC RIP T IO N

NoAudioInput The player has no audio input. This could be because they
do not have an audio device plugged in or they are having
an error with audio.

Muted The player is muted.

MutedByPlatform The player is muted due to platform policies. For example, a


player may have privacy settings to not allow
communication with other players.

Silent The player is not talking.

Talking The player is talking.


DeliveryOption
5/24/2022 • 2 minutes to read • Edit Online

The type of delivery guarantee for a message.

Syntax
public enum DeliveryOption
{
BestEffort,
Guaranteed
}

Constants
C O N STA N T DESC RIP T IO N

BestEffor t The message is sent without reliability or sequential


guarantees.

Guaranteed The message is guaranteed to arrive and in the correct order.


DirectPeerConnectivityOptions
5/24/2022 • 2 minutes to read • Edit Online

Flags controlling the attempted use of direct peer-to-peer connectivity among devices on a network.

Syntax
public enum PARTY_DIRECT_PEER_CONNECTIVITY_OPTIONS : UInt32
{
PARTY_DIRECT_PEER_CONNECTIVITY_OPTIONS_NONE = 0x0000,
PARTY_DIRECT_PEER_CONNECTIVITY_OPTIONS_SAME_PLATFORM_TYPE = 0x0001,
PARTY_DIRECT_PEER_CONNECTIVITY_OPTIONS_DIFFERENT_PLATFORM_TYPE = 0x0002,
PARTY_DIRECT_PEER_CONNECTIVITY_OPTIONS_ANY_PLATFORM_TYPE = 0x0003,
PARTY_DIRECT_PEER_CONNECTIVITY_OPTIONS_SAME_ENTITY_LOGIN_PROVIDER = 0x0004,
PARTY_DIRECT_PEER_CONNECTIVITY_OPTIONS_DIFFERENT_ENTITY_LOGIN_PROVIDER = 0x0008,
PARTY_DIRECT_PEER_CONNECTIVITY_OPTIONS_ANY_ENTITY_LOGIN_PROVIDER = 0x000c,
}

Constants
C O N STA N T DESC RIP T IO N

PARTY_DIRECT_PEER_CONNECTIVITY_OPTIONS_NONE No flags are specified.

The absence of flags means that no direct peer connectivity


attempts are permitted. All endpoint messages and chat
data between devices will always be transmitted via
transparent cloud relay servers, and no IP address
information will ever be exchanged.

PARTY_DIRECT_PEER_CONNECTIVITY_OPTIONS_SAME_PLAT Direct peer-to-peer connections may be attempted between


FORM_TYPE devices of the same platform type.

A pair of devices will attempt to establish direct peer-to-peer


connections if they're identified as having the same type of
hardware and/or OS platform (for example, Windows PCs,
Xbox gaming consoles, iOS-based mobile devices) associated
with the specific Party library they use.

Note that this flag doesn't permit any direct peer-to-peer


connectivity attempts by itself. It must be combined with
one or both of the
PARTY_DIRECT_PEER_CONNECTIVITY_OPTIONS_SAME_ENTITY_LOGIN_PROVIDER
and
PARTY_DIRECT_PEER_CONNECTIVITY_OPTIONS_DIFFERENT_ENTITY_LOGIN_PROVIDER
flags.

PARTY_DIRECT_PEER_CONNECTIVITY_OPTIONS_DIFFERENT_ Direct peer-to-peer connections may be attempted between


PLATFORM_TYPE devices with differing platform types.

A pair of devices will attempt to establish direct peer-to-peer


connections if they're identified as having different types of
hardware and/or OS platforms (for example, Windows PCs,
Xbox gaming consoles, iOS-based mobile devices) associated
with the specific Party libraries each device uses.

Note that this flag doesn't permit any direct peer-to-peer


connectivity attempts by itself. It must be combined with
one or both of the
PARTY_DIRECT_PEER_CONNECTIVITY_OPTIONS_SAME_ENTITY_LOGIN_PROVIDER
and
PARTY_DIRECT_PEER_CONNECTIVITY_OPTIONS_DIFFERENT_ENTITY_LOGIN_PROVIDER
flags.
C O N STA N T DESC RIP T IO N

PARTY_DIRECT_PEER_CONNECTIVITY_OPTIONS_ANY_PLATF Direct peer-to-peer connections may be attempted between


ORM_TYPE devices regardless of their platform types.

This flag is equivalent to


PARTY_DIRECT_PEER_CONNECTIVITY_OPTIONS_SAME_PLATFORM_TYPE |
PARTY_DIRECT_PEER_CONNECTIVITY_OPTIONS_DIFFERENT_PLATFORM_TYPE
.

PARTY_DIRECT_PEER_CONNECTIVITY_OPTIONS_SAME_ENTI Direct peer-to-peer connections may be attempted between


TY_LOGIN_PROVIDER devices that have authenticated user PlayFab Entity IDs that
were logged in using the same provider.

A device that's initially authenticating a local user into the


network will attempt to establish direct peer-to- peer
connections with remote devices that have at least one
authenticated user PlayFab Entity ID that was logged in
using the same provider (for example, Xbox Live, Facebook,
iOS, Google) as the newly authenticating user.

Note that this flag doesn't permit any direct peer-to-peer


connectivity attempts by itself. It must be combined with
one or both of the
PARTY_DIRECT_PEER_CONNECTIVITY_OPTIONS_SAME_PLATFORM_TYPE
and
PARTY_DIRECT_PEER_CONNECTIVITY_OPTIONS_DIFFERENT_PLATFORM_TYPE
flags.

PARTY_DIRECT_PEER_CONNECTIVITY_OPTIONS_DIFFERENT_ Direct peer-to-peer connections may be attempted between


ENTITY_LOGIN_PROVIDER devices with authenticated user PlayFab Entity IDs that that
were logged in using different providers.

A device that's initially authenticating a local user into the


network will attempt to establish direct peer-to- peer
connections with remote devices that don't have any
authenticated user PlayFab Entity IDs that were logged in
using the same provider (for example, Xbox Live, Facebook,
iOS, Google) as the newly authenticating user.

Note that this flag doesn't permit any direct peer-to-peer


connectivity attempts by itself. It must be combined with
one or both of the
PARTY_DIRECT_PEER_CONNECTIVITY_OPTIONS_SAME_PLATFORM_TYPE
and
PARTY_DIRECT_PEER_CONNECTIVITY_OPTIONS_DIFFERENT_PLATFORM_TYPE
flags.

PARTY_DIRECT_PEER_CONNECTIVITY_OPTIONS_ANY_ENTIT Direct peer-to-peer connections may be attempted between


Y_LOGIN_PROVIDER devices regardless of the provider used to login
authenticated user PlayFab Entity IDs.

This flag is equivalent to


SameEntiPARTY_DIRECT_PEER_CONNECTIVITY_OPTIONS_SAME_ENTITY_LOGIN_PROVIDERtyLoginProv
| PARTY_DIRECT_PEER_CONNECTIVITY_OPTIONS_DIFFERENT_ENTITY_LOGIN_PROVIDER
.
LogLevelType
5/24/2022 • 2 minutes to read • Edit Online

The amount of logging that is enabled.

Syntax
public enum PlayFabMultiplayerManager.LogLevelType
{
None,
Minimal,
Verbose
}

Constants
C O N STA N T DESC RIP T IO N

None

Minimal

Verbose
PlayFabMultiplayerManagerErrorType
5/24/2022 • 2 minutes to read • Edit Online

The types of errors PlayFabMultiplayerManager can raise.

Syntax
public enum PlayFabMultiplayerManagerErrorType
{
Unknown,
Error,
NetworkCreateError,
NetworkJoinError,
NetworkLeaveError
}

Constants
C O N STA N T DESC RIP T IO N

Unknown The type of error is unknown.

Error The error is a generic error.

NetworkCreateError The error is related to creating a network.

NetworkJoinError The error is related to joining a network.

NetworkLeaveError The error is related to leaving a network.


PlayFabMultiplayerManagerState
5/24/2022 • 2 minutes to read • Edit Online

The possible states that PlayFabMultiplayerManager can be in.

Syntax
public enum PlayFabMultiplayerManagerState
{
NotInitialized,
Initialized,
ConnectingToNetwork,
ConnectedToNetwork
}

Constants
C O N STA N T DESC RIP T IO N

NotInitialized PlayFabMultiplayerManager is not initialized.

Initialized PlayFabMultiplayerManager is initialized, but not connected


to a network.

ConnectingToNetwork PlayFabMultiplayerManager is initialized and in the process


of connecting to a network.

ConnectedToNetwork PlayFabMultiplayerManager is initialized and connected to a


network. At this point messages can be sent and received.
PartyXboxLive C/C++ API overview
5/24/2022 • 2 minutes to read • Edit Online

Classes
C L A SS DESC RIP T IO N

PartyXblChatUser The management class for Xbox Live operations related to a


chat user.

PartyXblLocalChatUser The management class for Xbox Live operations related to a


local chat user. Inherits from PartyXblChatUser.

PartyXblManager The primary management class for interacting with the Party
Xbox Live Helper library.

Structures
ST RUC T URE DESC RIP T IO N

PartyXblAccessibilitySettings Accessibility settings associated with an Xbox Live account.

PartyXblChatPermissionInfo Information regarding a required chat permission.

PartyXblHttpHeader Information about an HTTP header.

PartyXblXboxUserIdToPlayFabEntityIdMapping Mapping between an Xbox Live User Id and a PlayFab Entity


Id.

State changes
STAT E C H A N GE DESC RIP T IO N

PartyXblCreateLocalChatUserCompletedStateChange Information specific to the CreateLocalChatUserCompleted


type of state change.

PartyXblGetEntityIdsFromXboxLiveUserIdsCompletedStateCh Information specific to the


ange GetEntityIdsFromXboxLiveUserIdsCompleted type of state
change.

PartyXblLocalChatUserDestroyedStateChange Information specific to the LocalChatUserDestroyed type of


state change.

PartyXblLoginToPlayFabCompletedStateChange Information specific to the LoginToPlayFabCompleted type of


state change.

PartyXblRequiredChatPermissionInfoChangedStateChange Information specific to the


RequiredChatPermissionInfoChanged type of state change.
STAT E C H A N GE DESC RIP T IO N

PartyXblStateChange A generic, base structure representation of an event or


change in state.

PartyXblTokenAndSignatureRequestedStateChange Information specific to the TokenAndSignatureRequested


type of state change.

Enumerations
EN UM ERAT IO N DESC RIP T IO N

PartyXblChatPermissionMaskReason Reasons communication may be restricted.

PartyXblCrossNetworkCommunicationPrivacySetting Possible cross-network communication privacy settings for a


local Xbox Live user.

PartyXblLocalChatUserDestroyedReason Reasons a local chat user object might be destroyed.

PartyXblStateChangeResult Results for operations that generate state changes.

PartyXblStateChangeType The types of state changes that can occur.

PartyXblThreadId Threads that Party Xbox Live Helper library uses for internal
purposes.
PartyXblChatUser
5/24/2022 • 2 minutes to read • Edit Online

The management class for Xbox Live operations related to a chat user.

Syntax
class PartyXblChatUser

Public Methods
NAME DESC RIP T IO N

GetLocal Gets the PartyXblLocalChatUser version of this chat user.

GetXboxUserId Gets the Xbox Live User Id associated with this user.

GetCustomContext Retrieves the app's private, custom pointer-sized context


value previously associated with this local chat user object.

SetCustomContext Configures an optional, custom pointer-sized context value


with this local chat user object.

Requirements
Header : PartyXboxLive.h

See also
PartyXboxLive members
PartyXblLocalChatUser
PartyXblChatUser::GetLocal
5/24/2022 • 2 minutes to read • Edit Online

Gets the PartyXblLocalChatUser version of this chat user.

Syntax
PartyError GetLocal(
PartyXblLocalChatUser** localChatUser
)

Parameters
localChatUser PartyXblLocalChatUser**
library-allocated output, may return nullptr
The output local version of this chat user object, or nullptr if this is not a local chat user.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyXblManager::GetErrorMessage().

Requirements
Header : PartyXboxLive.h

See also
PartyXblChatUser
PartyXblChatUser::GetXboxUserId
5/24/2022 • 2 minutes to read • Edit Online

Gets the Xbox Live User Id associated with this user.

Syntax
PartyError GetXboxUserId(
uint64_t* xboxUserId
)

Parameters
xboxUserId uint64_t*
output
The output Xbox Live User Id.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyXblManager::GetErrorMessage().

Requirements
Header : PartyXboxLive.h

See also
PartyXblChatUser
PartyXblChatUser::GetCustomContext
5/24/2022 • 2 minutes to read • Edit Online

Retrieves the app's private, custom pointer-sized context value previously associated with this local chat user
object.

Syntax
PartyError GetCustomContext(
void** customContext
)

Parameters
customContext void**
output, may return nullptr
The output custom context.
Return value
PartyError
c_partyErrorSuccess if retrieving the custom context succeeded or an error code otherwise. The human-
readable form of the error code can be retrieved via PartyXblManager::GetErrorMessage().

Remarks
If no custom context has been set yet, the value pointed to by customContext is set to nullptr.

Requirements
Header : PartyXboxLive.h

See also
PartyXblChatUser
PartyXblChatUser::SetCustomContext
PartyXblChatUser::SetCustomContext
5/24/2022 • 2 minutes to read • Edit Online

Configures an optional, custom pointer-sized context value with this local chat user object.

Syntax
PartyError SetCustomContext(
void* customContext
)

Parameters
customContext void*
optional
An arbitrary, pointer-sized value to store with the chat user object.
Return value
PartyError
c_partyErrorSuccess if configuring the custom context succeeded or an error code otherwise. The human-
readable form of the error code can be retrieved via PartyXblManager::GetErrorMessage().

Remarks
The custom context is typically used as a "shortcut" that simplifies accessing local, title-specific memory
associated with the chat user without requiring a mapping lookup. The value is retrieved using the
GetCustomContext() method.

Any configured value is treated as opaque by the library, and is only valid on the local device; it is not
transmitted over the network.

Requirements
Header : PartyXboxLive.h

See also
PartyXblChatUser
PartyXblChatUser::GetCustomContext
PartyXblLocalChatUser
5/24/2022 • 2 minutes to read • Edit Online

The management class for Xbox Live operations related to a local chat user. Inherits from PartyXblChatUser.

Syntax
class PartyXblLocalChatUser : public PartyXblChatUser

Public Methods
NAME DESC RIP T IO N

GetAccessibilitySettings Returns the accessibility settings associated with this chat


user.

GetRequiredChatPermissionInfo Gets the cached required chat permission information


related to a target chat user.

GetCrossNetworkCommunicationPrivacySetting Gets the cross-network communication privacy setting for


this chat user.

Requirements
Header : PartyXboxLive.h

See also
PartyXboxLive members
PartyXblChatUser
PartyXblChatUser::GetLocal
PartyXblLocalChatUser::GetAccessibilitySettings
5/24/2022 • 2 minutes to read • Edit Online

Returns the accessibility settings associated with this chat user.

Syntax
PartyError GetAccessibilitySettings(
PartyXblAccessibilitySettings* settings
)

Parameters
settings PartyXblAccessibilitySettings*
output
The output accessibility settings.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyXblManager::GetErrorMessage().

Remarks
This function will fail until a PartyXblCreateLocalChatUserCompletedStateChange is provided by
PartyXblManager::StartProcessingStateChanges().

Requirements
Header : PartyXboxLive.h

See also
PartyXblLocalChatUser
PartyXblCreateLocalChatUserCompletedStateChange
PartyXblLocalChatUser::GetRequiredChatPermissionInfo
5/24/2022 • 2 minutes to read • Edit Online

Gets the cached required chat permission information related to a target chat user.

Syntax
PartyError GetRequiredChatPermissionInfo(
const PartyXblChatUser* targetChatUser,
PartyXblChatPermissionInfo* chatPermissionInfo
)

Parameters
targetChatUser PartyXblChatUser*
The chat user for which permissions relative to the local chat user should be retrieved.
chatPermissionInfo PartyXblChatPermissionInfo*
output
The output chat permission info object. The chat permission info object contains the most permissive chat
permission possible while still respecting Xbox Live requirements.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyXblManager::GetErrorMessage().

Requirements
Header : PartyXboxLive.h

See also
PartyXblLocalChatUser
PartyXblCreateLocalChatUserCompletedStateChange
PartyXblRequiredChatPermissionInfoChangedStateChange
PartyXblLocalChatUser::GetCrossNetworkCommunicationPrivacySetting
5/24/2022 • 2 minutes to read • Edit Online

Gets the cross-network communication privacy setting for this chat user.

Syntax
PartyError GetCrossNetworkCommunicationPrivacySetting(
PartyXblCrossNetworkCommunicationPrivacySetting* setting
)

Parameters
setting PartyXblCrossNetworkCommunicationPrivacySetting*
output
The output cross-network communication privacy setting.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PartyXblManager::GetErrorMessage().

Remarks
A cross-network user is defined as a user of a non-Xbox Live gaming network.

Requirements
Header : PartyXboxLive.h

See also
PartyXblLocalChatUser
PartyXblManager
5/24/2022 • 2 minutes to read • Edit Online

The primary management class for interacting with the Party Xbox Live Helper library.

Syntax
class PartyXblManager

Public Methods
NAME DESC RIP T IO N

GetSingleton Retrieves a reference to the PartyXblManager singleton


instance.

GetErrorMessage Get the human-readable form of an error.

SetMemoryCallbacks Optionally configures the memory allocation and freeing


callbacks the Party Xbox Live Helper library should use.

GetMemoryCallbacks Retrieves the current memory allocation and freeing


callbacks the Party Xbox Live library is using.

SetThreadAffinityMask Optionally configures the processor on which internal Party


Xbox Live Helper library threads will run.

GetThreadAffinityMask Retrieves the current set of processors on which internal


Party Xbox Live Helper library threads will run or are running
as an affinity mask.

Initialize Initializes the object instance.

Cleanup Immediately reclaims all resources associated with the object.

StartProcessingStateChanges Retrieves an array of all Party Xbox Live state changes to


process since the last such call.

FinishProcessingStateChanges Returns an array of Party Xbox Live state changes that were
being processed.

CompleteGetTokenAndSignatureRequest Completes a GetTokenAndSignature operation.

CreateLocalChatUser Queues an asynchronous attempt to create a local chat user.


Privacy and privilege information related to this user will be
tracked by the helper library.
NAME DESC RIP T IO N

CreateRemoteChatUser Creates a remote chat user. A remote chat user is an Xbox


Live user currently communicating with at least one local
user. Creating a remote chat user will cause the library to
start tracking privacy information related to this user in
relation to every local chat user.

DestroyChatUser Destroys a chat user.

GetChatUsers Gets an array containing all chat users created by


CreateLocalChatUser() and CreateRemoteChatUser().

LoginToPlayFab Signs the user in to PlayFab using an Xbox Live token,


asynchronously returning an Entity Id and Entity Token that
can subsequently be used for PlayFab API calls which require
an authenticated PlayFab user or to create a PartyLocalUser.
There is no difference between calling this method or using
the LoginWithXbox method provided by the PlayFab SDK.

GetEntityIdsFromXboxLiveUserIds Queues an asynchronous operation to retrieve a list of


mappings between PlayFab Entity Ids and known Xbox Live
User Ids.

Remarks
Only a single instance of the class is permitted.

Requirements
Header : PartyXboxLive.h

See also
PartyXboxLive members
PartyXblManager::GetSingleton
5/24/2022 • 2 minutes to read • Edit Online

Retrieves a reference to the PartyXblManager singleton instance.

Syntax
PartyXblManager& GetSingleton(
)

Parameters
Return value
PartyXblManager&
The PartyXblManager singleton instance.

Requirements
Header : PartyXboxLive.h

See also
PartyXblManager
PartyXblManager::GetErrorMessage
5/24/2022 • 2 minutes to read • Edit Online

Get the human-readable form of an error.

Syntax
PartyError GetErrorMessage(
PartyError error,
PartyString* errorMessage
)

Parameters
error PartyError

An error code.
errorMessage PartyString*
library-allocated output
The output, human-readable error message. The memory for the returned string remains valid for the lifetime
of the process.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise.

Remarks
These error messages are not localized and are only intended for developers, i.e. these error messages are not
intended to be shown to users via UI.

Requirements
Header : PartyXboxLive.h

See also
PartyXblManager
PartyXblManager::SetMemoryCallbacks
5/24/2022 • 2 minutes to read • Edit Online

Optionally configures the memory allocation and freeing callbacks the Party Xbox Live Helper library should
use.

Syntax
PartyError SetMemoryCallbacks(
PartyAllocateMemoryCallback allocateMemoryCallback,
PartyFreeMemoryCallback freeMemoryCallback
)

Parameters
allocateMemoryCallback PartyAllocateMemoryCallback
A pointer to the custom allocation callback to use.
freeMemoryCallback PartyFreeMemoryCallback
A pointer to the custom freeing callback to use.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise.

Remarks
This method allows the application to install custom memory allocation routines in order to service all requests
by the Party Xbox Live Helper library for new memory buffers instead of using its default allocation routines.

The allocateMemoryCallback and freeMemoryCallback parameters must both be non-null.

To use this method, it must be called before any other Party Xbox Live Helper library method except for
GetMemoryCallbacks(). This method cannot be called again for the lifetime of this process.

Requirements
Header : PartyXboxLive.h

See also
PartyXblManager
PartyXblManager::GetMemoryCallbacks
PartyXblManager::GetMemoryCallbacks
5/24/2022 • 2 minutes to read • Edit Online

Retrieves the current memory allocation and freeing callbacks the Party Xbox Live library is using.

Syntax
PartyError GetMemoryCallbacks(
PartyAllocateMemoryCallback* allocateMemoryCallback,
PartyFreeMemoryCallback* freeMemoryCallback
)

Parameters
allocateMemoryCallback PartyAllocateMemoryCallback*
output
A place to store a pointer to the memory allocation callback currently used.
freeMemoryCallback PartyFreeMemoryCallback*
output
A place to store a pointer to the memory freeing callback currently used.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via GetErrorMessage().

Remarks
This method does not require the Initialize() method to have been called first.

Requirements
Header : PartyXboxLive.h

See also
PartyXblManager
PartyXblManager::SetMemoryCallbacks
PartyXblManager::SetThreadAffinityMask
5/24/2022 • 2 minutes to read • Edit Online

Optionally configures the processor on which internal Party Xbox Live Helper library threads will run.

Syntax
PartyError SetThreadAffinityMask(
PartyXblThreadId threadId,
uint64_t threadAffinityMask
)

Parameters
threadId PartyXblThreadId

The type of internal library thread for which processor affinity should be retrieved.
threadAffinityMask uint64_t
The affinity mask for this type of Party thread.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via GetErrorMessage().

Remarks
This method enables the application to configure the processor affinity for internal Party Xbox Live Helper
library thread of a given type.

This method may be called at any time before or after Initialize() and will take effect immediately. Thread
processor settings are persisted across calls to Cleanup() and Initialize(). When there are more than 64 cores
present, this method always applies to processor group 0.

In order to specify any processor, pass c_anyProcessor as the threadAffinityMask parameter. This is also the
default value the Party Xbox Live Helper library will use if this method is never called.

Requirements
Header : PartyXboxLive.h

See also
PartyXblManager
PartyXblThreadId
PartyXblManager::GetThreadAffinityMask
PartyXblManager::GetThreadAffinityMask
5/24/2022 • 2 minutes to read • Edit Online

Retrieves the current set of processors on which internal Party Xbox Live Helper library threads will run or are
running as an affinity mask.

Syntax
PartyError GetThreadAffinityMask(
PartyXblThreadId threadId,
uint64_t* threadAffinityMask
)

Parameters
threadId PartyXblThreadId

The type of internal library thread for which processor affinity should be retrieved.
threadAffinityMask uint64_t*
output
A place to store the affinity mask for this type of Party thread.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via GetErrorMessage().

Remarks
This retrieves the current processor affinity for internal Party threads Xbox Live Helper library of a given type.

This method does not require Initialize() to have been called first.

A reported value of c_anyProcessor written to threadAffinityMask indicates that the thread is free to run on any
processor.

Requirements
Header : PartyXboxLive.h

See also
PartyXblManager
PartyXblManager::SetThreadAffinityMask
PartyXblManager::Initialize
5/24/2022 • 2 minutes to read • Edit Online

Initializes the object instance.

Syntax
PartyError Initialize(
PartyString titleId
)

Parameters
titleId PartyString

The app's PlayFab Title Id.


Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via GetErrorMessage().

Remarks
This must be called before any other method under the PartyXblManager namespace, aside from the static
methods GetSingleton(), SetMemoryCallbacks(), GetMemoryCallbacks(), SetThreadAffinityMask(),
GetThreadAffinityMask(). Initialize() cannot be called again without a subsequent Cleanup() call.

Every call to Initialize() should have a corresponding Cleanup() call.

It is recommended for apps using the Xbox One XDK version of the Party Xbox Live Helper library to wait until
the platform is ready for networking operations before calling this method. Please refer to the XDK
documentation about networking and secure device associations best practices for more information.

Apps using the Microsoft Game Core version of the Party Xbox Live Helper library will need to wait for the
Game Core Networking stack to be initialized prior to calling this method. Determining the status of the network
stack can be done using the Game Core XNetworkingGetConnectivityHint API.

Apps using the Microsoft Game Core version of the Party Xbox Live Helper library must listen for app state
notifications via the RegisterAppStateChangeNotification API. When the app is suspended, the title must call
Cleanup(). When the app is resumed, the title must wait for the Game Core networking stack to be ready and
then re-initialize the Party Xbox Live Helper library by calling Initialize().

Requirements
Header : PartyXboxLive.h

See also
PartyXblManager
PartyXblManager::Cleanup
PartyXblManager::GetSingleton
PartyXblManager::SetMemoryCallbacks
PartyXblManager::GetMemoryCallbacks
PartyXblManager::SetThreadAffinityMask
PartyXblManager::GetThreadAffinityMask
PartyXblManager::Cleanup
5/24/2022 • 2 minutes to read • Edit Online

Immediately reclaims all resources associated with the object.

Syntax
PartyError Cleanup(
)

Parameters
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via GetErrorMessage().

Remarks
Every call to Initialize() should have a corresponding Cleanup() call.

Titles using the Microsoft Game Core version of the Party Xbox Live Helper library must listen for app state
notifications via the RegisterAppStateChangeNotification API. When the app is suspended, the title must call
Cleanup(). When the app is resumed, the title must wait for the Game Core networking stack to be ready and
then re-initialize the Party Xbox Live Helper library by calling Initialize().

Requirements
Header : PartyXboxLive.h

See also
PartyXblManager
PartyXblManager::Initialize
PartyXblManager::StartProcessingStateChanges
5/24/2022 • 2 minutes to read • Edit Online

Retrieves an array of all Party Xbox Live state changes to process since the last such call.

Syntax
PartyError StartProcessingStateChanges(
uint32_t* stateChangeCount,
PartyXblStateChangeArray* stateChanges
)

Parameters
stateChangeCount uint32_t*
output
A place to write the number of PartyXblStateChange entries for the title to handle in the stateChanges array.
stateChanges PartyXblStateChangeArray*
library-allocated output array of size *stateChangeCount
A place to store a pointer to the array of all PartyXblStateChange entries for the title to handle and then pass to
FinishProcessingStateChanges().
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via GetErrorMessage().

Remarks
This method provides the Party Xbox Live Helper library an opportunity to retrieves a list of all changes
currently available for the title since the last call to this method. The title should use the provided array of 0 or
more changes to update its own state or UI, and then call FinishProcessingStateChanges() with them in a timely
manner.

State exposed by the library can change during this call, so you must be thread-safe in your use of it.
StartProcessingStateChanges() should be called frequently-- at least once every 100 milliseconds. It's designed
to execute and return quickly such that it can be called on your main UI thread with negligible impact. For best
results, you should also minimize the time you spend handling state changes before calling
FinishProcessingStateChanges().

Each state change returned by StartProcessingStateChanges() must be returned to


FinishProcessingStateChanges() exactly once, but may be returned out of order and may be interleaved with
state changes from other calls to StartProcessingStateChanges(). Any resources associated with a specific state
change are guaranteed to stay valid until the state change is returned to FinishProcessingStateChanges().

Requirements
Header : PartyXboxLive.h

See also
PartyXblManager
PartyXblStateChange
PartyXblManager::FinishProcessingStateChanges
PartyXblManager::FinishProcessingStateChanges
5/24/2022 • 2 minutes to read • Edit Online

Returns an array of Party Xbox Live state changes that were being processed.

Syntax
PartyError FinishProcessingStateChanges(
uint32_t stateChangeCount,
PartyXblStateChangeArray stateChanges
)

Parameters
stateChangeCount uint32_t
The number of changes, provided in the list specified by stateChanges , previously returned by
StartProcessingStateChanges() that have now been handled by the title.
stateChanges PartyXblStateChangeArray
input array of size stateChangeCount
The pointer to the array of changes previously returned by StartProcessingStateChanges() that have now been
handled by the title.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via GetErrorMessage().

Remarks
This method informs the Party Xbox Live Helper library that the state changes reported by a previous call to
StartProcessingStateChanges() have now been handled by the title, so their associated resources can be
reclaimed. You may call FinishProcessingStateChanges() with any number of state changes. Each state change
returned by StartProcessingStateChanges() must be returned to FinishProcessingStateChanges() exactly once,
but may be returned out of order and may be interleaved with state changes from other calls to
StartProcessingStateChanges(). Even if state changes are held across subsequent calls to
StartProcessingStateChanges(), the Party Xbox Live Helper library state returned by all getters will advance and
may no longer reflect the same state that the held state changes refer to.

Any resources associated with a specific state change are guaranteed to stay valid until the state change is
returned to FinishProcessingStateChanges().

For best results, you should minimize the time you spend handling state changes before calling
FinishProcessingStateChanges().

Requirements
Header : PartyXboxLive.h
See also
PartyXblManager
PartyXblStateChange
PartyXblManager::StartProcessingStateChanges
PartyXblManager::CompleteGetTokenAndSignatureRequest
5/24/2022 • 2 minutes to read • Edit Online

Completes a GetTokenAndSignature operation.

Syntax
PartyError CompleteGetTokenAndSignatureRequest(
uint32_t correlationId,
PartyBool succeeded,
PartyString token,
PartyString signature
)

Parameters
correlationId uint32_t
The correlation id of the web request for which the token and signature were requested.
succeeded PartyBool
The title succeeded the token and signature request.
token PartyString
optional
The token for the request, if necessary, as a null terminated string.
signature PartyString
optional
The signature for the request, if necessary, as a null terminated string.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via GetErrorMessage().

Remarks
The title can use the Xbox Authentication Library (XAL) to fulfill these request by calling the
XalUserGetTokenAndSignatureSilentlyAsync function.
This should only be called in response to a PartyXblTokenAndSignatureRequestedStateChange.

Requirements
Header : PartyXboxLive.h

See also
PartyXblManager
PartyXblTokenAndSignatureRequestedStateChange
PartyXblManager::CreateLocalChatUser
5/24/2022 • 2 minutes to read • Edit Online

Queues an asynchronous attempt to create a local chat user. Privacy and privilege information related to this
user will be tracked by the helper library.

Syntax
PartyError CreateLocalChatUser(
uint64_t xboxUserId,
void* asyncIdentifier,
PartyXblLocalChatUser** localChatUser
)

Parameters
xboxUserId uint64_t
The Xbox Live User Id associated with the local chat user.
asyncIdentifier void*
optional
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
localChatUser PartyXblLocalChatUser**
optional, library-allocated output
The output local chat user object.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via GetErrorMessage().

Requirements
Header : PartyXboxLive.h

See also
PartyXblManager
PartyXblManager::CreateRemoteChatUser
5/24/2022 • 2 minutes to read • Edit Online

Creates a remote chat user. A remote chat user is an Xbox Live user currently communicating with at least one
local user. Creating a remote chat user will cause the library to start tracking privacy information related to this
user in relation to every local chat user.

Syntax
PartyError CreateRemoteChatUser(
uint64_t xboxUserId,
PartyXblChatUser** chatUser
)

Parameters
xboxUserId uint64_t
The Xbox Live user id associated with the chat user.
chatUser PartyXblChatUser**
optional, library-allocated output
The output chat user object.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via GetErrorMessage().

Requirements
Header : PartyXboxLive.h

See also
PartyXblManager
PartyXblManager::DestroyChatUser
5/24/2022 • 2 minutes to read • Edit Online

Destroys a chat user.

Syntax
PartyError DestroyChatUser(
const PartyXblChatUser* chatUser
)

Parameters
chatUser PartyXblChatUser*

The chat user object to be destroyed.


Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via GetErrorMessage().

Requirements
Header : PartyXboxLive.h

See also
PartyXblManager
PartyXblManager::GetChatUsers
5/24/2022 • 2 minutes to read • Edit Online

Gets an array containing all chat users created by CreateLocalChatUser() and CreateRemoteChatUser().

Syntax
PartyError GetChatUsers(
uint32_t* userCount,
PartyXblChatUserArray* chatUsers
)

Parameters
userCount uint32_t*
output
An output value indicating the number of chat users provided in chatUsers .
chatUsers PartyXblChatUserArray*
library-allocated output array of size *endpointCount

A library-allocated output array containing the local and remote chat users.
Return value
PartyError
c_partyErrorSuccess if the call succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via GetErrorMessage().

Remarks
The array is backed by the library's internal memory. The array is only valid until the next call to either
CreateLocalChatUser(), CreateRemoteChatUser(), StartProcessingStateChanges() or DestroyChatUser(). A call to
DestroyChatUser() will also immediately invalidate the chat user object.

Requirements
Header : PartyXboxLive.h

See also
PartyXblManager
PartyXblManager::CreateLocalChatUser
PartyXblManager::CreateRemoteChatUser
PartyXblManager::DestroyChatUser
PartyXblManager::LoginToPlayFab
5/24/2022 • 2 minutes to read • Edit Online

Signs the user in to PlayFab using an Xbox Live token, asynchronously returning an Entity ID and Entity Token
that can subsequently be used for PlayFab API calls which require an authenticated PlayFab user or to create a
PartyLocalUser. There is no difference between calling this method or using the LoginWithXbox method
provided by the PlayFab SDK.

Syntax
PartyError LoginToPlayFab(
const PartyXblLocalChatUser* localChatUser,
void* asyncIdentifier
)

Parameters
localChatUser PartyXblLocalChatUser*
The local chat user object that will be used for the login operation.
asyncIdentifier void*
optional
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
Return value
PartyError
c_partyErrorSuccessif the operation to login the local chat user with PlayFab started or an error code
otherwise. The human-readable form of the error code can be retrieved via GetErrorMessage().

Remarks
If this is the first time the Xbox Live identity has logged in to PlayFab, a new PlayFab account will be created and
linked to the Xbox Live identity.

When a token is nearing the expiration time or if a token has expired due to the application being in a dormant
state for an extended time, a new token should be obtained by calling this method. It is recommended to acquire
a new token when the previously supplied token is halfway through its validity period.

Requirements
Header : PartyXboxLive.h

See also
PartyXblManager
PartyXblLoginToPlayFabCompletedStateChange
PartyXblManager::GetEntityIdsFromXboxLiveUserIds
5/24/2022 • 2 minutes to read • Edit Online

Queues an asynchronous operation to retrieve a list of mappings between PlayFab Entity Ids and known Xbox
Live User Ids.

Syntax
PartyError GetEntityIdsFromXboxLiveUserIds(
uint32_t xboxLiveUserIdCount,
const uint64_t* xboxLiveUserIds,
const PartyXblLocalChatUser* localChatUser,
void* asyncIdentifier
)

Parameters
xboxLiveUserIdCount uint32_t
The number of Xbox Live User Ids in the xboxLiveUserIds array.
xboxLiveUserIds uint64_t*
input array of size xboxLiveUserIdCount

An array of size xboxLiveUserIdCount containing the Xbox Live User Ids for which the library will query the
PlayFab Entity Id.
localChatUser PartyXblLocalChatUser*
Local chat user that will be used to communicate with PlayFab. The local chat user will be logged in to PlayFab if
needed.
asyncIdentifier void*
optional
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
Return value
PartyError
c_partyErrorSuccess if the operation started or an error code otherwise. The human-readable form of the error
code can be retrieved via GetErrorMessage().

Remarks
Each Xbox Live User Id will only map to a PlayFab Entity Id if this Xbox Live User has already been linked to a
PlayFab account. A PlayFab account is automatically created and linked when calling
PartyXblManager::LoginToPlayFab for the first time. The LoginWithXbox API provided by the PlayFab SDK can
also be used to link an account.

If the PartyXblGetEntityIdsFromXboxLiveUserIdsCompletedStateChange associated with the completion of this


call indicates a failure with a result of PartyXblStateChangeResult::PlayFabUserNotAuthorized, the operation can
be retried no more than one time after successfully calling LoginToPlayFab().

If the PartyXblGetEntityIdsFromXboxLiveUserIdsCompletedStateChange associated with the completion of this


call indicates a failure with a result of PartyXblStateChangeResult::PlayFabRateLimitExceeded, the operation can
be retried after a brief delay.

Requirements
Header : PartyXboxLive.h

See also
PartyXblManager
PartyXblGetEntityIdsFromXboxLiveUserIdsCompletedStateChange
PartyXblAccessibilitySettings
5/24/2022 • 2 minutes to read • Edit Online

Accessibility settings associated with an Xbox Live account.

Syntax
struct PartyXblAccessibilitySettings {
PartyBool speechToTextEnabled;
PartyBool textToSpeechEnabled;
char languageCode[c_maxLanguageCodeStringLength + 1];
PartyGender gender;
}

Members
speechToTextEnabled PartyBool
True if the user has enabled speech to text in its Xbox Live settings
textToSpeechEnabled PartyBool
True if the user has enabled text to speech in its Xbox Live settings
languageCode char[c_maxLanguageCodeStringLength + 1]
Language code associated with this user's accessibility settings. Can be used as a hint when choosing the
PartyTextToSpeechProfile for this user.
gender PartyGender
Gender associated with this user's accessibility settings. Can be used as a hint when choosing the
PartyTextToSpeechProfile for this user.

Requirements
Header : PartyXboxLive.h

See also
PartyXboxLive members
PartyXblChatPermissionInfo
5/24/2022 • 2 minutes to read • Edit Online

Information regarding a required chat permission.

Syntax
struct PartyXblChatPermissionInfo {
PartyChatPermissionOptions chatPermissionMask;
PartyXblChatPermissionMaskReason reason;
}

Members
chatPermissionMask PartyChatPermissionOptions
The chat permission options mask that should be applied to the target chat user.
Use a bitwise 'AND' operation against the desired chat permissions to ensure the resulting permissions will
respect Xbox Live policies.
reason PartyXblChatPermissionMaskReason
Extra information regarding the result of a required chat permission query.

Requirements
Header : PartyXboxLive.h

See also
PartyXboxLive members
PartyXblHttpHeader
5/24/2022 • 2 minutes to read • Edit Online

Information about an HTTP header.

Syntax
struct PartyXblHttpHeader {
PartyString name;
PartyString value;
}

Members
name PartyString

The header's name.


value PartyString
The header's value.

Requirements
Header : PartyXboxLive.h

See also
PartyXboxLive members
PartyXblXboxUserIdToPlayFabEntityIdMapping
5/24/2022 • 2 minutes to read • Edit Online

Mapping between an Xbox Live User Id and a PlayFab Entity Id.

Syntax
struct PartyXblXboxUserIdToPlayFabEntityIdMapping {
uint64_t xboxLiveUserId;
PartyString playfabEntityId;
}

Members
xboxLiveUserId uint64_t
The Xbox Live User Id.
playfabEntityId PartyString
The PlayFab Entity Id.
This value may be an empty string in the case where the Xbox Live user does not have a linked PlayFab account.
A PlayFab account is automatically created and linked when calling PartyXblManager::LoginToPlayFab for the
first time. The LoginWithXbox API provided by the PlayFab SDK can also be used to link an account.

Requirements
Header : PartyXboxLive.h

See also
PartyXboxLive members
PartyXblCreateLocalChatUserCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the CreateLocalChatUserCompleted type of state change.

Syntax
struct PartyXblCreateLocalChatUserCompletedStateChange : PartyXblStateChange {
PartyXblStateChangeResult result;
PartyError errorDetail;
void* asyncIdentifier;
PartyXblLocalChatUser* localChatUser;
}

Members
result PartyXblStateChangeResult

Indicates that the local chat user creation operation Succeeded or provides the reason that it failed.
errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
asyncIdentifier void*
The async identifier provided to the call associated with this state change.
localChatUser PartyXblLocalChatUser*
The local chat user that was created.

Requirements
Header : PartyXboxLive.h

See also
PartyXboxLive members
PartyXblGetEntityIdsFromXboxLiveUserIdsCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the GetEntityIdsFromXboxLiveUserIdsCompleted type of state change.

Syntax
struct PartyXblGetEntityIdsFromXboxLiveUserIdsCompletedStateChange : PartyXblStateChange {
PartyXblStateChangeResult result;
PartyError errorDetail;
PartyString xboxLiveSandbox;
PartyXblLocalChatUser* localChatUser;
void* asyncIdentifier;
uint32_t entityIdMappingCount;
const PartyXblXboxUserIdToPlayFabEntityIdMapping* entityIdMappings;
}

Members
result PartyXblStateChangeResult

Indicates that the operation succeeded or the reason that it failed.


errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
xboxLiveSandbox PartyString
The device's Xbox Live sandbox which was used for this operation.
localChatUser PartyXblLocalChatUser*
The local chat user that was used to communicate with PlayFab.
asyncIdentifier void*
The async identifier provided to the call associated with this state change.
entityIdMappingCount uint32_t
The number of Xbox Live User Id to PlayFab Entity Id mappings.
entityIdMappings const PartyXblXboxUserIdToPlayFabEntityIdMapping*
array of size entityIdMappingCount

A list of Xbox Live User Id to PlayFab Entity Id mappings.

Requirements
Header : PartyXboxLive.h

See also
PartyXboxLive members
PartyXblLocalChatUserDestroyedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the LocalChatUserDestroyed type of state change.

Syntax
struct PartyXblLocalChatUserDestroyedStateChange : PartyXblStateChange {
PartyXblLocalChatUser* localChatUser;
PartyXblLocalChatUserDestroyedReason reason;
PartyError errorDetail;
}

Members
localChatUser PartyXblLocalChatUser*
The local chat user provided to the call associated with this state change.
reason PartyXblLocalChatUserDestroyedReason
The reason the local chat user was destroyed.
errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
The human-readable form of this error detail can be retrieved via PartyXblManager::GetErrorMessage().

Requirements
Header : PartyXboxLive.h

See also
PartyXboxLive members
PartyXblLoginToPlayFabCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the LoginToPlayFabCompleted type of state change.

Syntax
struct PartyXblLoginToPlayFabCompletedStateChange : PartyXblStateChange {
PartyXblStateChangeResult result;
PartyError errorDetail;
PartyXblLocalChatUser* localChatUser;
void* asyncIdentifier;
PartyString entityId;
PartyString titlePlayerEntityToken;
time_t expirationTime;
}

Members
result PartyXblStateChangeResult

Indicates that the login operation succeeded or the reason that it failed.
errorDetail PartyError
A diagnostic value providing additional troubleshooting information regarding any potential error condition.
localChatUser PartyXblLocalChatUser*
The local chat user who was logged in to PlayFab.
asyncIdentifier void*
The async identifier provided to the call associated with this state change.
entityId PartyString
The PlayFab Entity Id associated with the local chat user's Xbox Live identity.
titlePlayerEntityToken PartyString
The PlayFab Entity Token associated with the local chat user's Xbox Live identity.
expirationTime time_t
The timestamp describing when this token expires.
When the token is nearing the expiration time or if the token has expired due to the application being in a
dormant state for an extended time, a new token should be obtained by calling
PartyXblManager::LoginToPlayFab().

Requirements
Header : PartyXboxLive.h

See also
PartyXboxLive members
PartyXblRequiredChatPermissionInfoChangedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the RequiredChatPermissionInfoChanged type of state change.

Syntax
struct PartyXblRequiredChatPermissionInfoChangedStateChange : PartyXblStateChange {
PartyXblLocalChatUser* localChatUser;
PartyXblChatUser* targetChatUser;
}

Members
localChatUser PartyXblLocalChatUser*
The local chat user for which the chat permission info applies to.
targetChatUser PartyXblChatUser*
The chat user the chat permission info should be applied to.

Remarks
Use PartyXblLocalChatUser::GetRequiredChatPermissionInfo() with the targetChatUser provided in this state
change to get the new chat permission information.

Requirements
Header : PartyXboxLive.h

See also
PartyXboxLive members
PartyXblStateChange
5/24/2022 • 2 minutes to read • Edit Online

A generic, base structure representation of an event or change in state.

Syntax
struct PartyXblStateChange {
PartyXblStateChangeType stateChangeType;
}

Members
stateChangeType PartyXblStateChangeType
The specific type of the state change represented.
Use this field to determine which corresponding derived structure is represented by this PartyXblStateChange
structure header.

Remarks
PartyXblStateChange structures are reported by PartyXblManager::StartProcessingStateChanges() for the title to
handle and then promptly pass back via the PartyXblManager::FinishProcessingStateChanges() method.

The stateChangeType field indicates which kind of state change occurred, and this base structure should then be
cast to a more specific derived structure to retrieve additional event-specific information.

Requirements
Header : PartyXboxLive.h

See also
PartyXboxLive members
PartyXblManager::StartProcessingStateChanges
PartyXblManager::FinishProcessingStateChanges
PartyXblTokenAndSignatureRequestedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the TokenAndSignatureRequested type of state change.

Syntax
struct PartyXblTokenAndSignatureRequestedStateChange : PartyXblStateChange {
uint32_t correlationId;
PartyString method;
PartyString url;
uint32_t headerCount;
PartyXblHttpHeader* headers;
uint32_t bodySize;
const void* body;
PartyBool forceRefresh;
PartyBool allUsers;
PartyXblLocalChatUser* localChatUser;
}

Members
correlationId uint32_t
Opaque identifier used to associate the token and signature request with the internal HTTP request. Use this
identifier when calling PartyXblManager::CompleteGetTokenAndSignatureRequest() to complete the operation.
method PartyString
The HTTP method for the request, such as "GET" or "POST".
url PartyString
The URL for the HTTP request that needs a token and signature (fully escaped).
headerCount uint32_t
The number of headers for the HTTP request.
headers PartyXblHttpHeader*
array of size headerCount
The headers for the HTTP request.
bodySize uint32_t
The size of the request body in bytes.
body const void*
buffer of size bodySize bytes
The request body.
forceRefresh PartyBool
If true the token must be refreshed, ignoring any cached token.
allUsers PartyBool
If true , a token should be requested for all users rather than a specific user. In the case localChatUser will be
nullptr.
localChatUser PartyXblLocalChatUser*
may be nullptr
The local chat user that should be used to retrieve the token and signature.
This field is only valid when allUsers is set to false .

Remarks
The title can use the Xbox Authentication Library (XAL) to fulfill these requests by calling the
XalUserGetTokenAndSignatureSilentlyAsync() function.

Use PartyXblManager::CompleteGetTokenAndSignatureRequest() to provide the token and signature and


complete the operation.

Requirements
Header : PartyXboxLive.h

See also
PartyXboxLive members
PartyXblChatPermissionMaskReason
5/24/2022 • 2 minutes to read • Edit Online

Reasons communication may be restricted.

Syntax
enum class PartyXblChatPermissionMaskReason
{
NoRestriction,
Determining,
Privilege,
Privacy,
InvalidTargetUser,
XboxLiveServiceError,
UnknownError,
ResolveUserIssue,
}

Constants
C O N STA N T DESC RIP T IO N

NoRestriction There is no restriction currently applying to this chat


permission.

Determining Communication is restricted while the local chat user's


communication privilege and privacy settings are being
queried.

Privilege Communication is restricted due to the local chat user's


communication privilege.

If this mask is generated by the Microsoft Game Core


version of the library, the app can call
XUserResolvePrivilegeWithUiAsync with
XUserPrivilegeOptions::None and
XUserPrivilege::Communications to attempt to resolve the
issue. The user may be unable or unwilling to resolve the
issue. If the user does resolve the issue, the user's chat
permission will be updated and a new
PartyXblRequiredChatPermissionInfoChangedStateChange
state change will be generated.

Privacy Communication is restricted due to the local chat user's


privacy settings in relation to the target chat user.

InvalidTargetUser Communication is restricted because the target user was not


recognized as valid by Xbox Live services.

XboxLiveServiceError The required chat permission could not be successfully


determined due to issues with Xbox Live services.
C O N STA N T DESC RIP T IO N

UnknownError The required chat permission could not be successfully


determined due to an unknown internal error.

ResolveUserIssue Communication is restricted due to a failure in retrieving the


user's privileges.

This mask reason will only be generated by the Microsoft


Game Core version of the library. The library on other
platforms will only ever generate the Privilege mask reason
to expose privilege errors. The app can call
XUserResolveIssueWithUiAsync with nullptr for the URL
parameter to attempt to resolve the issue. The user may be
unable or unwilling to resolve the issue. If the user does
resolve the issue, the user's chat permission will be updated
and a new
PartyXblRequiredChatPermissionInfoChangedStateChange
state change will be generated.

Requirements
Header : PartyXboxLive.h

See also
PartyXboxLive members
PartyXblCrossNetworkCommunicationPrivacySetting
5/24/2022 • 2 minutes to read • Edit Online

Possible cross-network communication privacy settings for a local Xbox Live user.

Syntax
enum class PartyXblCrossNetworkCommunicationPrivacySetting
{
Allowed,
FriendsOnly,
Disallowed,
}

Constants
C O N STA N T DESC RIP T IO N

Allowed Communication with cross-network users is allowed with no


restriction for this user.

FriendsOnly Communication with cross-network users is restricted to


friends only for this user.

Disallowed Communication with cross-network users is not allowed for


this user.

Remarks
A cross-network user is defined as a user of a non-Xbox Live gaming network.

Requirements
Header : PartyXboxLive.h

See also
PartyXboxLive members
PartyXblLocalChatUserDestroyedReason
5/24/2022 • 2 minutes to read • Edit Online

Reasons a local chat user object might be destroyed.

Syntax
enum class PartyXblLocalChatUserDestroyedReason
{
UnauthorizedLocalChatUser,
FailedToGetTokenAndSignatureForLocalChatUser,
XboxLiveServiceTemporarilyUnavailable,
InternetConnectivityError,
XboxLiveUserNotSignedIn,
UnknownError,
}

Constants
C O N STA N T DESC RIP T IO N

UnauthorizedLocalChatUser The user is not authorized to communicate with the Xbox


Live service.

On the Windows 10 platform this can be caused by an


invalid token or signature provided to the library by calling
PartyXblManager::CompleteGetTokenAndSignatureRequest().

FailedToGetTokenAndSignatureForLocalChatUser A valid token and/or signature for an HTTP request could


not be acquired.

XboxLiveServiceTemporarilyUnavailable The Xbox Live service is temporarily unavailable.

InternetConnectivityError The local device has internet connectivity issues which


caused the operation to fail.

XboxLiveUserNotSignedIn The Xbox Live user associated with the


PartyXblLocalChatUser is not currently signed-in on the
device.

UnknownError An unknown error occurred.

Requirements
Header : PartyXboxLive.h

See also
PartyXboxLive members
PartyXblStateChangeResult
5/24/2022 • 2 minutes to read • Edit Online

Results for operations that generate state changes.

Syntax
enum class PartyXblStateChangeResult
{
Succeeded,
UnknownError,
CanceledByTitle,
UserNotAuthorized,
LoginToPlayFabThrottled,
PartyServiceError,
XboxLiveServiceTemporarilyUnavailable,
InternetConnectivityError,
PlayFabRateLimitExceeded,
}

Constants
C O N STA N T DESC RIP T IO N

Succeeded The operation succeeded.

UnknownError An unknown error occurred.

CanceledByTitle Another title operation canceled this operation.

UserNotAuthorized The Xbox Live user or PlayFab Entity associated with the
PartyXblLocalChatUser is not authorized to perform this
request.

LoginToPlayFabThrottled The operation failed because too many logins have been
attempted for this title.

PartyServiceError The operation failed because of an unexpected error in the


Party Service.

XboxLiveServiceTemporarilyUnavailable The Xbox Live service is temporarily unavailable.

InternetConnectivityError The local device has internet connectivity issues which


caused the operation to fail.

PlayFabRateLimitExceeded The rate limit for the PlayFab Service has been reached.

Requirements
Header : PartyXboxLive.h
See also
PartyXboxLive members
PartyXblStateChangeType
5/24/2022 • 2 minutes to read • Edit Online

The types of state changes that can occur.

Syntax
enum class PartyXblStateChangeType : uint32_t
{
CreateLocalChatUserCompleted,
LocalChatUserDestroyed,
RequiredChatPermissionInfoChanged,
TokenAndSignatureRequested,
LoginToPlayFabCompleted,
GetEntityIdsFromXboxLiveUserIdsCompleted,
}

Constants
C O N STA N T DESC RIP T IO N

CreateLocalChatUserCompleted The operation started by a previous call to


PartyXblManager::CreateLocalChatUser() completed.

The PartyXblStateChange object should be cast to a


PartyXblCreateLocalChatUserCompletedStateChange.

LocalChatUserDestroyed A local chat user was destroyed.

The PartyXblStateChange object should be cast to a


PartyXblLocalChatUserDestroyedStateChange object for
more information.

RequiredChatPermissionInfoChanged Chat permissions between a local chat user and a target chat
user has changed.

The PartyXblStateChange object should be cast to a


PartyXblRequiredChatPermissionInfoChangedStateChange
object for more information.
C O N STA N T DESC RIP T IO N

TokenAndSignatureRequested The Xbox Live Helper library requires an Xbox Live token and
signature to complete an HTTP request.

The title can use the Xbox Authentication Library (XAL) to


fulfill these request by calling the
XalUserGetTokenAndSignatureSilentlyAsync function.

The title needs to call


PartyXblManager::CompleteGetTokenAndSignatureRequest()
with the request token and signature.

The PartyXblStateChange object should be cast to a


PartyXblTokenAndSignatureRequestedStateChange object for
more information.

This state change is only returned on the Windows 10


platform.

LoginToPlayFabCompleted The operation started by a previous call to


PartyXblManager::LoginToPlayFab() completed.

The PartyXblStateChange object should be cast to a


PartyXblLoginToPlayFabCompletedStateChange object for
more information.

GetEntityIdsFromXboxLiveUserIdsCompleted The operation started by a previous call to


PartyXblManager::GetEntityIdsFromXboxLiveUserIds()
completed.

The PartyXblStateChange object should be cast to a


PartyXblGetEntityIdsFromXboxLiveUserIdsCompletedStateCh
ange object for more information.

Requirements
Header : PartyXboxLive.h

See also
PartyXboxLive members
PartyXblThreadId
5/24/2022 • 2 minutes to read • Edit Online

Threads that Party Xbox Live Helper library uses for internal purposes.

Syntax
enum class PartyXblThreadId
{
WebRequest,
}

Constants
C O N STA N T DESC RIP T IO N

WebRequest Represents the Party Xbox Live Helper library internal web
request threads.

The internal networking thread is driven from both network


I/O and polling mechanisms. It wakes every 50 to 100
milliseconds or whenever network traffic is received.

Requirements
Header : PartyXboxLive.h

See also
PartyXboxLive members
PartyXblManager::GetThreadAffinityMask
PartyXblManager::SetThreadAffinityMask
PlayFab Party Xbox Live Helper Libary Typedefs
5/24/2022 • 2 minutes to read • Edit Online

The Party Xbox Live Helper Library uses several typedefs for convenient declarations of arrays of core types.
Additional typedefs provided by PlayFab Party are used within the PlayFab Party Xbox Live Helper Library.

Arrays
A number of structs and method parameters use constant arrays of core types. To simplify usage and
declaration of these arrays, the following typedefs are provided.

typedef const struct PartyXblStateChange * const * PartyXblStateChangeArray;


typedef class PartyXblChatUser * const * PartyXblChatUserArray;

T Y P EDEF C O RE T Y P E

PartyXblStateChangeArray PartyXblStateChange

PartyXblChatUserArray PartyLocalUser

Requirements
Header : PartyXboxLive.h

See also
Party typedefs
PFMultiplayer C/C++ API overview -
PFMultiplayer.h
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

Functions
F UN C T IO N DESC RIP T IO N

PFMultiplayerGetErrorMessage Get the human-readable form of an error.

PFMultiplayerInitialize Initializes an instance of the PlayFab Multiplayer library.

PFMultiplayerSetEntityToken Sets the token that should be used for authentication when
performing library actions on behalf of an entity. If a token
has previously been set for the entity, this replaces its
previous token.

PFMultiplayerSetMemoryCallbacks Optionally configures the memory allocation and freeing


callbacks the Multiplayer library should use.

PFMultiplayerSetThreadAffinityMask Optionally configures the processor on which internal


Multiplayer library threads will run.

PFMultiplayerUninitialize Immediately reclaims all resources associated with all


Multiplayer library objects.

Callbacks
C ALLBAC K DESC RIP T IO N

PFMultiplayerAllocateMemoryCallback A callback invoked every time a new memory buffer must be


dynamically allocated by the PlayFab Multiplayer library.

PartyFreeMemoryCallback A callback invoked every time a previously allocated memory


buffer is no longer needed by the PlayFab Multiplayer library
and can be freed.

Enumerations
EN UM ERAT IO N DESC RIP T IO N

PFMultiplayerThreadId Threads that Multiplayer library uses for internal purposes.


PFMultiplayer C/C++ API overview - PFLobby.h
5/24/2022 • 3 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

Functions
F UN C T IO N DESC RIP T IO N

PFLobbyAddMember Add a local user as a member to the lobby.

PFLobbyForceRemoveMember Forcibly remove an entity from the lobby.

PFLobbyGetAccessPolicy Gets the access policy of the lobby.

PFLobbyGetConnectionString Gets the default connection string associated with the lobby.

PFLobbyGetCustomContext Retrieves the app's private, custom pointer-sized context


value previously associated with this lobby object.

PFLobbyGetLobbyId Gets the ID of the Lobby.

PFLobbyGetLobbyProperty Get the lobby property value from its key.

PFLobbyGetLobbyPropertyKeys Get the list of lobby property keys.

PFLobbyGetMaxMemberCount Gets the max member count of the lobby.

PFLobbyGetMemberProperty Get the member property's value from its key.

PFLobbyGetMemberPropertyKeys Get a list of the specified member's property keys.

PFLobbyGetMembers Gets the list of PlayFab entities currently joined to the lobby
as members.

PFLobbyGetMembershipLock Gets the lobby's current membership lock state.

PFLobbyGetOwner Gets the current owner of the lobby.

PFLobbyGetOwnerMigrationPolicy Gets the owner migration policy of the lobby.

PFLobbyGetSearchProperty Get the search property value from its key.

PFLobbyGetSearchPropertyKeys Get the list of search property keys.


F UN C T IO N DESC RIP T IO N

PFLobbyLeave Request one or all local users to leave the lobby.

PFLobbyPostUpdate Post an update to the lobby.

PFLobbySendInvite Send an invite to this lobby from the local user to the invited
entity.

PFLobbySetCustomContext Configures an optional, custom pointer-sized context value


with this lobby object.

PFMultiplayerCreateAndJoinLobby Create a new lobby and add the creating PlayFab entity to it.

PFMultiplayerFindLobbies Search for lobbies on behalf of the local user.

PFMultiplayerFinishProcessingLobbyStateChanges Returns an array of PFLobbyStateChanges that were being


processed.

PFMultiplayerGetLobbyInviteListenerStatus Retrieve the status of the entity's invite listener.

PFMultiplayerJoinArrangedLobby Joins a lobby using an arrangement string provided by


another service, such as matchmaking. If no one has joined
the lobby yet, the lobby is initialized using the configuration
parameters.

PFMultiplayerJoinLobby Join a lobby as the local PlayFab entity.

PFMultiplayerStartListeningForLobbyInvites Enables the Lobby invite listener for a given entity.

PFMultiplayerStartProcessingLobbyStateChanges Retrieves an array of all PFLobbyStateChanges to process


since the last such call.

PFMultiplayerStopListeningForLobbyInvites Disables the Lobby invite listener for a given entity.

Structures
ST RUC T URE DESC RIP T IO N

PFLobbyArrangedJoinConfiguration The initial configuration data used when joining an arranged


lobby.

PFLobbyCreateConfiguration The initial configuration data used when creating a lobby.

PFLobbyDataUpdate A request to make an update to the shared portion of the


lobby on behalf of a member.

PFLobbyJoinConfiguration The initial configuration data used when joining a lobby.

PFLobbyMemberDataUpdate A request to make an update to the member-owned portion


of the lobby document.
ST RUC T URE DESC RIP T IO N

PFLobbyMemberUpdateSummary A collection of hints about an update which has been


successfully applied to the lobby on behalf of a member.

PFLobbySearchConfiguration The configuration structure used to specify how a


PFMultiplayerFindLobbies operation should be performed.

PFLobbySearchFriendsFilter The filter structure used to limit lobby search results to only
those lobbies owned by the player's friends.

PFLobbySearchResult An entry in the collection of lobby search results received


upon successful completion of a PFMultiplayerFindLobbies
operation.

State changes
STAT E C H A N GE DESC RIP T IO N

PFLobbyAddMemberCompletedStateChange Information specific to the AddMemberCompleted type of


state change.

PFLobbyCreateAndJoinLobbyCompletedStateChange Information specific to the CreateAndJoinLobbyCompleted


type of state change.

PFLobbyDisconnectedStateChange Information specific to the Disconnected type of state


change.

PFLobbyDisconnectingStateChange Information specific to the Disconnecting type of state


change.

PFLobbyFindLobbiesCompletedStateChange Information specific to the FindLobbiesCompleted type of


state change.

PFLobbyForceRemoveMemberCompletedStateChange Information specific to the ForceRemoveMemberCompleted


type of state change.

PFLobbyInviteListenerStatusChangedStateChange Information specific to the InviteListenerStatusChanged type


of state change.

PFLobbyInviteReceivedStateChange Information specific to the InviteReceived type of state


change.

PFLobbyJoinArrangedLobbyCompletedStateChange Information specific to the JoinArrangedLobbyCompleted


type of state change.

PFLobbyJoinLobbyCompletedStateChange Information specific to the JoinLobbyCompleted type of


state change.

PFLobbyLeaveLobbyCompletedStateChange Information specific to the LeaveLobbyCompleted type of


state change.

PFLobbyMemberAddedStateChange Information specific to the MemberAdded type of state


change.
STAT E C H A N GE DESC RIP T IO N

PFLobbyMemberRemovedStateChange Information specific to the MemberRemoved type of state


change.

PFLobbyPostUpdateCompletedStateChange Information specific to the PostUpdateCompleted type of


state change.

PFLobbySendInviteCompletedStateChange Information specific to the SendInviteCompleted type of


state change.

PFLobbyStateChange A generic, base structure representation of an event or


change in state.

PFLobbyUpdatedStateChange Information specific to the Updated type of state change.

Enumerations
EN UM ERAT IO N DESC RIP T IO N

PFLobbyAccessPolicy Values representing the lobby's access policy.

PFLobbyDisconnectingReason Reasons the client no longer has access to the Lobby.

PFLobbyInviteListenerStatus Values representing the current status of an invite listener.

PFLobbyMemberRemovedReason Reasons why a member was removed from a lobby.

PFLobbyMembershipLock Values representing the state of the lobby's membership


lock.

PFLobbyOwnerMigrationPolicy The available policies the lobby service can use to migrate
lobby ownership between members.

PFLobbyStateChangeType The types of state changes that can occur.


PFMultiplayer C/C++ API overview -
PFMatchmaking.h
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

Functions
F UN C T IO N DESC RIP T IO N

PFMatchmakingTicketCancel Cancels the ticket.

PFMatchmakingTicketGetMatch Provides the match, if one has been found.

PFMatchmakingTicketGetStatus Provides the matchmaking ticket status.

PFMatchmakingTicketGetTicketId Provides the ticket ID.

PFMultiplayerCreateMatchmakingTicket Creates a matchmaking ticket for one or more local users.

PFMultiplayerDestroyMatchmakingTicket Destroys the matchmaking ticket.

PFMultiplayerFinishProcessingMatchmakingStateChanges Returns an array of matchmaking state changes that were


being processed.

PFMultiplayerJoinMatchmakingTicketFromId Joins one or more multiple local users to a matchmaking


ticket using a ticket ID and queue name.

PFMultiplayerStartProcessingMatchmakingStateChanges Retrieves an array of all matchmaking state changes to


process since the last such call.

Structures
ST RUC T URE DESC RIP T IO N

PFMatchmakingMatchDetails The resulting match information found by a completed


ticket.

PFMatchmakingMatchMember A member of a match result.

PFMatchmakingTicketConfiguration Defines the configuration for a matchmaking ticket.

State changes
STAT E C H A N GE DESC RIP T IO N

PFMatchmakingStateChange A generic, base structure representation of an event or


change in state.

PFMatchmakingTicketCompletedStateChange Information specific to the TicketCompleted type of state


change.

PFMatchmakingTicketStatusChangedStateChange Information specific to the TicketStatusChanged type of state


change.

Enumerations
EN UM ERAT IO N DESC RIP T IO N

PFMatchmakingStateChangeType The types of state changes that can occur.

PFMatchmakingTicketStatus The possible states for a matchmaking ticket.


PFMultiplayerGetErrorMessage
5/24/2022 • 2 minutes to read • Edit Online

Get the human-readable form of an error.

Syntax
const char * PFMultiplayerGetErrorMessage(
HRESULT error
)

Parameters
error HRESULT

An error code.
Return value
Type: const char *
The human-readable error message. The memory for the returned string remains valid for the lifetime of the
process.

Remarks
These error messages are not localized and are only intended for developers, i.e. these error messages are not
intended to be shown to users via UI.

Requirements
Header : PFMultiplayer.h

See also
PFMultiplayer members
PFMultiplayerInitialize
5/24/2022 • 2 minutes to read • Edit Online

Initializes an instance of the PlayFab Multiplayer library.

Syntax
HRESULT PFMultiplayerInitialize(
const char* playFabTitleId,
PFMultiplayerHandle* handle
)

Parameters
playFabTitleId char*
is null-terminated
The app's PlayFab Title ID.
handle PFMultiplayerHandle*
library-allocated output
The output handle of the newly initialized PFMultiplayer API instance.
Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
This must be called before any other method, aside from PFMultiplayerSetMemoryCallbacks(), and
PFMultiplayerSetThreadAffinityMask(). PFMultiplayerInitialize() cannot be called again without a subsequent
PFMultiplayerUninitialize() call.

Every call to PFMultiplayerInitialize() should have a corresponding PFMultiplayerUninitialize() call.

Apps using the Microsoft Game Core version of the Multiplayer library will need to wait for the Game Core
Networking stack to be initialized prior to calling this method. Determining the status of the network stack can
be done using the Game Core XNetworkingGetConnectivityHint API.

The provided playFabTitleId must be the same PlayFab Title ID used to acquire the PlayFab Entity Keys and
Entity Tokens that will be passed to PFMultiplayerSetEntityToken().

Requirements
Header : PFMultiplayer.h

See also
PFMultiplayer members
PFMultiplayerSetEntityToken
PFMultiplayerUninitialize
PFMultiplayerSetMemoryCallbacks
PFMultiplayerSetThreadAffinityMask
PFMultiplayerSetEntityToken
5/24/2022 • 2 minutes to read • Edit Online

Sets the token that should be used for authentication when performing library actions on behalf of an entity. If a
token has previously been set for the entity, this replaces its previous token.

Syntax
HRESULT PFMultiplayerSetEntityToken(
PFMultiplayerHandle handle,
const PFEntityKey* entity,
const char* entityToken
)

Parameters
handle PFMultiplayerHandle

The handle of the PFMultiplayer API instance.


entity PFEntityKey*
The PlayFab Entity Key to associate with a token.
entityToken char*
is null-terminated
TBD
Return value
Type: HRESULT
S_OK if creating the local user succeeded or an error code otherwise. The human-readable form of the error
code can be retrieved via PFMultiplayerGetErrorMessage().

Remarks
This method takes a PlayFab Entity Key as entity and a PlayFab Entity Token as token . When the library
performs operations on behalf of an entity that require authentication or authorization, such as creating or
updating a lobby, the library will look up a token associated with the entity to use for the operation. If no token
has previously been set for the entity, the operation will synchronously fail. During the asynchronous operation,
the PlayFab service will validate that the token is valid, is not expired, is associated with the Entity ID provided,
and is authorized to perform the operation. If these conditions aren't met, the operation will fail.

A PlayFab Entity Key and Entity Token can be obtained from the output of a PlayFab login operation and then
provided as input to this method.

The provided entity and token must have been acquired using the same PlayFab Title ID that was passed to
PFMultiplayerInitialize().

The Multiplayer library makes a copy of the supplied PlayFab Entity Token for use in subsequent operations that
require authentication or authorization of the local user, such as PFMultiplayerCreateAndJoinLobby . If the token
provided to this call is expired or otherwise invalid, operations that require a valid token will fail. A new, valid
token can be provided to the Multiplayer library by calling this method again using the same entity key.

The caller is responsible for monitoring the expiration of the entity token provided to this method. When the
token is nearing or past the expiration time a new token should be obtained by performing a PlayFab login
operation and provided to the Multiplayer library by calling this method again. It is recommended to acquire a
new token when the previously supplied token is halfway through its validity period. On platforms that may
enter a low power state or otherwise cause the application to pause execution for a long time, preventing the
token from being refreshed before it expires, the token should be checked for expiration once execution
resumes.

No synchronous validation is performed on these values.

Requirements
Header : PFMultiplayer.h

See also
PFMultiplayer members
PFMultiplayerInitialize
PFMultiplayerSetMemoryCallbacks
5/24/2022 • 2 minutes to read • Edit Online

Optionally configures the memory allocation and freeing callbacks the Multiplayer library should use.

Syntax
HRESULT PFMultiplayerSetMemoryCallbacks(
PFMultiplayerAllocateMemoryCallback allocateMemoryCallback,
PFMultiplayerFreeMemoryCallback freeMemoryCallback
)

Parameters
allocateMemoryCallback PFMultiplayerAllocateMemoryCallback
A pointer to the custom allocation callback to use.
freeMemoryCallback PFMultiplayerFreeMemoryCallback
A pointer to the custom freeing callback to use.
Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
This method allows the title to install custom memory allocation functions in order to service all requests by the
Multiplayer library for new memory buffers instead of using its default allocation functions.

The allocateMemoryCallback and freeMemoryCallback parameters must both be non-null.

To use this method, it must be called before any other Multiplayer method. This method cannot be called again
for the lifetime of this process.

Requirements
Header : PFMultiplayer.h

See also
PFMultiplayer members
PFMultiplayerAllocateMemoryCallback
PFMultiplayerFreeMemoryCallback
PFMultiplayerSetThreadAffinityMask
5/24/2022 • 2 minutes to read • Edit Online

Optionally configures the processor on which internal Multiplayer library threads will run.

Syntax
HRESULT PFMultiplayerSetThreadAffinityMask(
PFMultiplayerThreadId threadId,
uint64_t threadAffinityMask
)

Parameters
threadId PFMultiplayerThreadId

The type of internal Multiplayer library thread to configure processor affinity.


threadAffinityMask uint64_t
The affinity mask for this type of Multiplayer library thread.
Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
This method enables the title to configure the processor affinity for internal Multiplayer library threads of a
given type.

This method may be called at any time before or after PFMultiplayerInitialize() and will take effect immediately.
Thread processor settings are persisted across calls to PFMultiplayerUninitialize() and PFMultiplayerInitialize().
When there are more than 64 cores present, this method always applies to processor group 0.

In order to specify any processor, pass PFMultiplayerAnyProcessor as the threadAffinityMask parameter. This is
also the default value the Multiplayer library will use if this method is never called.

Requirements
Header : PFMultiplayer.h

See also
PFMultiplayer members
PFMultiplayerThreadId
PFMultiplayerUninitialize
5/24/2022 • 2 minutes to read • Edit Online

Immediately reclaims all resources associated with all Multiplayer library objects.

Syntax
HRESULT PFMultiplayerUninitialize(
PFMultiplayerHandle handle
)

Parameters
handle PFMultiplayerHandle
input not valid afterwards
The handle of the PFMultiplayer API instance.
Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
If local users were participating in a Lobby, they are removed (it appears to remote lobby clients as if network
connectivity to these users has been lost), so best practice is to call PFLobbyLeave on all lobbies and wait for the
corresponding PFLobbyLeaveLobbyCompletedStateChange to have the local users exit any existing lobbies.

This method is not thread-safe and may not be called concurrently with other Multiplayer library methods. After
calling this method, all Multiplayer library state is invalidated.

Every call to PFMultiplayerInitialize() should have a corresponding PFMultiplayerUninitialize() call.

Requirements
Header : PFMultiplayer.h

See also
PFMultiplayer members
PFMultiplayerInitialize
PFLobbyAddMember
5/24/2022 • 2 minutes to read • Edit Online

Add a local user as a member to the lobby.

Syntax
HRESULT PFLobbyAddMember(
PFLobbyHandle lobby,
const PFEntityKey* localUser,
uint32_t memberPropertyCount,
const char* const* memberPropertyKeys,
const char* const* memberPropertyValues,
void* asyncContext
)

Parameters
lobby PFLobbyHandle

The handle of the lobby.


localUser PFEntityKey*
The PlayFab Entity Key of the local user to add to the lobby as a member.
memberPropertyCount uint32_t
input in range 0,PFLobbyMaxMemberPropertyCount

The number of initial member properties to set for this user when they join the lobby.
memberPropertyKeys char* const*
input array of size memberPropertyCount

The keys of the initial member properties to set for this user when they join the lobby.
memberPropertyValues char* const*
input array of size memberPropertyCount

The values of the initial member properties to set for this user when they join the lobby.
asyncContext void*
optional
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
This is an asynchronous operation. Upon successful completion, the title will be provided a
PFLobbyMemberAddedStateChange followed by a PFLobbyAddMemberCompletedStateChange with the
PFLobbyAddMemberCompletedStateChange::result field set to S_OK . Upon a failed completion, the title will be
provided a PFLobbyAddMemberCompletedStateChange with the
PFLobbyAddMemberCompletedStateChange::result field set to a failure hresult.

This method is used to add another local PlayFab entity to a pre-existing lobby object. Because the lobby object
must have already been created either via a call to PFMultiplayerCreateAndJoinLobby or
PFMultiplayerJoinLobby, this method is primarily useful for multiple local user scenarios.

This is an asynchronous operation. The member added via this method will not be reflected in the lists returned
by PFLobbyGetMembers until the asynchronous operation successfully completes and a
PFLobbyMemberAddedStateChange struct is provided by PFMultiplayerStartProcessingLobbyStateChanges.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyForceRemoveMember
5/24/2022 • 2 minutes to read • Edit Online

Forcibly remove an entity from the lobby.

Syntax
HRESULT PFLobbyForceRemoveMember(
PFLobbyHandle lobby,
const PFEntityKey* targetMember,
bool preventRejoin,
void* asyncContext
)

Parameters
lobby PFLobbyHandle

The handle of the lobby.


targetMember PFEntityKey*
The member to forcibly remove.
preventRejoin bool
A flag indicating whether targetMember will be prevented from rejoining the lobby after being removed.
asyncContext void*
optional
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
This is an asynchronous operation. Upon successful completion, the title will be provided a
PFLobbyMemberRemovedStateChange followed by a PFLobbyForceRemoveMemberCompletedStateChange
with the PFLobbyForceRemoveMemberCompletedStateChange::result field set to S_OK . Upon a failed
completion, the title will be provided a PFLobbyForceRemoveMemberCompletedStateChange with the
PFLobbyForceRemoveMemberCompletedStateChange::result field set to a failure hresult.

One of the local PlayFab entities present in this lobby must be the owner for this operation to succeed. If the
local owning entity who initiated this operation loses their ownership status while the operation is in progress,
the operation will fail asynchronously.

This is an asynchronous operation. The member removed via this method will not be removed from the lists
returned by PFLobbyGetMembers until the asynchronous operation successfully completes and a
PFLobbyMemberRemovedStateChange struct is provided by PFMultiplayerStartProcessingLobbyStateChanges.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyGetAccessPolicy
5/24/2022 • 2 minutes to read • Edit Online

Gets the access policy of the lobby.

Syntax
HRESULT PFLobbyGetAccessPolicy(
PFLobbyHandle lobby,
PFLobbyAccessPolicy* accessPolicy
)

Parameters
lobby PFLobbyHandle

The handle of the lobby.


accessPolicy PFLobbyAccessPolicy*
output
The output access policy.
Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
If this lobby object was created by calling PFMultiplayerJoinLobby(), this method will return an error until
PFMultiplayerStartProcessingLobbyStateChanges() provides a PFLobbyUpdatedStateChange with
PFLobbyUpdatedStateChange::accessPolicyUpdated set to true. If joining the lobby succeeds, this field is
guaranteed to be populated by the time PFMultiplayerStartProcessingLobbyStateChanges() provides a
PFLobbyJoinLobbyCompletedStateChange.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyGetConnectionString
5/24/2022 • 2 minutes to read • Edit Online

Gets the default connection string associated with the lobby.

Syntax
HRESULT PFLobbyGetConnectionString(
PFLobbyHandle lobby,
const char** connectionString
)

Parameters
lobby PFLobbyHandle

The handle of the lobby.


connectionString char**
library-allocated output
The output connection string.
Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
If this lobby object was created by calling PFMultiplayerCreateAndJoinLobby(), this method will return an error
until PFMultiplayerStartProcessingLobbyStateChanges() provides a successful
PFLobbyCreateAndJoinLobbyCompletedStateChange. If this lobby object was created by calling
PFMultiplayerJoinLobby(), this method will return an error until
PFMultiplayerStartProcessingLobbyStateChanges() provides a successful
PFLobbyJoinLobbyCompletedStateChange.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyGetCustomContext
5/24/2022 • 2 minutes to read • Edit Online

Retrieves the app's private, custom pointer-sized context value previously associated with this lobby object.

Syntax
HRESULT PFLobbyGetCustomContext(
PFLobbyHandle lobby,
void** customContext
)

Parameters
lobby PFLobbyHandle

The handle of the lobby.


customContext void**
output, may return nullptr
The output custom context.
Return value
Type: HRESULT
S_OK if retrieving the custom context succeeded or an error code otherwise. The human-readable form of the
error code can be retrieved via PFMultiplayerGetErrorMessage().

Remarks
If no custom context has been set yet, the value pointed to by customContext is set to nullptr.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbySetCustomContext
PFLobbyGetLobbyId
5/24/2022 • 2 minutes to read • Edit Online

Gets the ID of the Lobby.

Syntax
HRESULT PFLobbyGetLobbyId(
PFLobbyHandle lobby,
const char** id
)

Parameters
lobby PFLobbyHandle

The handle of the lobby.


id char**
library-allocated output
The output lobby ID.
Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
If this lobby object was created by calling PFMultiplayerCreateAndJoinLobby() or PFMultiplayerJoinLobby(), this
method will return an error until PFMultiplayerStartProcessingLobbyStateChanges() provides a successful
PFLobbyCreateAndJoinLobbyCompletedStateChange or PFLobbyJoinLobbyCompletedStateChange respectively.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyGetLobbyProperty
5/24/2022 • 2 minutes to read • Edit Online

Get the lobby property value from its key.

Syntax
HRESULT PFLobbyGetLobbyProperty(
PFLobbyHandle lobby,
const char* key,
const char** value
)

Parameters
lobby PFLobbyHandle

The handle of the lobby.


key char*
is null-terminated
The key of the property.
value char**
library-allocated output, may return nullptr
The output value associated with the key. An output null value signifies the property wasn't present.
Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
Lobby properties are only visible to members of the lobby.

If this lobby object is still in the process of asynchronously being created or joined via a call to
PFMultiplayerCreateAndJoinLobby() or PFMultiplayerJoinLobby(), this method will return no properties.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyGetLobbyPropertyKeys
5/24/2022 • 2 minutes to read • Edit Online

Get the list of lobby property keys.

Syntax
HRESULT PFLobbyGetLobbyPropertyKeys(
PFLobbyHandle lobby,
uint32_t* propertyCount,
const char* const** keys
)

Parameters
lobby PFLobbyHandle

The handle of the lobby.


propertyCount uint32_t*
output
The output count of lobby properties.
keys char* const**
library-allocated output array of size *propertyCount

The output array of lobby property keys.


Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
Lobby properties are only visible to members of the lobby.

If this lobby object is still in the process of asynchronously being created or joined via a call to
PFMultiplayerCreateAndJoinLobby() or PFMultiplayerJoinLobby(), this method will return no keys.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyGetMaxMemberCount
5/24/2022 • 2 minutes to read • Edit Online

Gets the max member count of the lobby.

Syntax
HRESULT PFLobbyGetMaxMemberCount(
PFLobbyHandle lobby,
uint32_t* maxMemberCount
)

Parameters
lobby PFLobbyHandle

The handle of the lobby.


maxMemberCount uint32_t*
output
The output max member count.
Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the result can be retrieved
via PFMultiplayerGetErrorMessage().

Remarks
If this lobby object was created by calling PFMultiplayerJoinLobby(), this method will return an error until
PFMultiplayerStartProcessingLobbyStateChanges() provides a PFLobbyUpdatedStateChange with
PFLobbyUpdatedStateChange::maxMembersUpdated set to true. If joining the lobby succeeds, this field is
guaranteed to be populated by the time PFMultiplayerStartProcessingLobbyStateChanges() provides a
PFLobbyJoinLobbyCompletedStateChange.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyGetMemberProperty
5/24/2022 • 2 minutes to read • Edit Online

Get the member property's value from its key.

Syntax
HRESULT PFLobbyGetMemberProperty(
PFLobbyHandle lobby,
const PFEntityKey* member,
const char* key,
const char** value
)

Parameters
lobby PFLobbyHandle

The handle of the lobby.


member PFEntityKey*
The member whose property bag we want to query.
key char*
is null-terminated
The key of the property.
value char**
library-allocated output, may return nullptr
The output value associated with the key. An output null value signifies the property wasn't present.
Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
Per-member properties are only visible to members of the lobby.

If the member is still in the process of asynchronously joining this lobby either via
PFMultiplayerCreateAndJoinLobby(), PFMultiplayerJoinLobby(), or PFLobbyAddMember(), this method will
return no properties.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyGetMemberPropertyKeys
5/24/2022 • 2 minutes to read • Edit Online

Get a list of the specified member's property keys.

Syntax
HRESULT PFLobbyGetMemberPropertyKeys(
PFLobbyHandle lobby,
const PFEntityKey* member,
uint32_t* propertyCount,
const char* const** keys
)

Parameters
lobby PFLobbyHandle

The handle of the lobby.


member PFEntityKey*
The member being queried.
propertyCount uint32_t*
output
The output count of member properties.
keys char* const**
library-allocated output array of size *propertyCount

The output array of member property keys.


Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
Per-member properties are only visible to members of the lobby.

If the member is still in the process of asynchronously joining this lobby either via
PFMultiplayerCreateAndJoinLobby(), PFMultiplayerJoinLobby(), or PFLobbyAddMember, this method will return
no keys.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyGetMembers
5/24/2022 • 2 minutes to read • Edit Online

Gets the list of PlayFab entities currently joined to the lobby as members.

Syntax
HRESULT PFLobbyGetMembers(
PFLobbyHandle lobby,
uint32_t* memberCount,
const PFEntityKey** members
)

Parameters
lobby PFLobbyHandle

The handle of the lobby.


memberCount uint32_t*
output
The output member count.
members PFEntityKey**
library-allocated output array of size *memberCount

The output member array.


Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
If this lobby object is still in the process of asynchronously being created or joined, via a call to either
PFMultiplayerCreateAndJoinLobby() or PFMultiplayerJoinLobby() respectively, this method will return no
members.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyGetMembershipLock
5/24/2022 • 2 minutes to read • Edit Online

Gets the lobby's current membership lock state.

Syntax
HRESULT PFLobbyGetMembershipLock(
PFLobbyHandle lobby,
PFLobbyMembershipLock* lockState
)

Parameters
lobby PFLobbyHandle

The handle of the lobby.


lockState PFLobbyMembershipLock*
output
The output membership lock state.
Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
If this lobby object was created by calling PFMultiplayerJoinLobby(), this method will return an error until
PFMultiplayerStartProcessingLobbyStateChanges() provides a PFLobbyUpdatedStateChange with
PFLobbyUpdatedStateChange::membershipLockUpdated set to true. If joining the lobby succeeds, this field is
guaranteed to be populated by the time PFMultiplayerStartProcessingLobbyStateChanges() provides a
PFLobbyJoinLobbyCompletedStateChange.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyGetOwner
5/24/2022 • 2 minutes to read • Edit Online

Gets the current owner of the lobby.

Syntax
HRESULT PFLobbyGetOwner(
PFLobbyHandle lobby,
const PFEntityKey** owner
)

Parameters
lobby PFLobbyHandle

The handle of the lobby.


owner PFEntityKey**
library-allocated output, may return nullptr
The output owner. This value may be null if the owner has left or disconnected from the lobby while the owner
migration policy is PFLobbyOwnerMigrationPolicy::Manual or PFLobbyOwnerMigrationPolicy::None.
Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
If this lobby object was created by calling PFMultiplayerJoinLobby(), this method will return an error until
PFMultiplayerStartProcessingLobbyStateChanges() provides a PFLobbyUpdatedStateChange with
PFLobbyUpdatedStateChange::ownerUpdated set to true. If joining the lobby succeeds, this field is guaranteed to
be populated by the time PFMultiplayerStartProcessingLobbyStateChanges() provides a
PFLobbyJoinLobbyCompletedStateChange.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyGetOwnerMigrationPolicy
5/24/2022 • 2 minutes to read • Edit Online

Gets the owner migration policy of the lobby.

Syntax
HRESULT PFLobbyGetOwnerMigrationPolicy(
PFLobbyHandle lobby,
PFLobbyOwnerMigrationPolicy* ownerMigrationPolicy
)

Parameters
lobby PFLobbyHandle

The handle of the lobby.


ownerMigrationPolicy PFLobbyOwnerMigrationPolicy*
output
The output owner migration policy.
Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
The owner migration policy cannot change for the lifetime of the lobby.

If this lobby object was created by calling PFMultiplayerJoinLobby(), this method will return an error until
PFMultiplayerStartProcessingLobbyStateChanges() provides a PFLobbyUpdatedStateChange with
PFLobbyUpdatedStateChange::ownerMigrationPolicy set to true. If joining the lobby succeeds, this field is
guaranteed to be populated by the time PFMultiplayerStartProcessingLobbyStateChanges() provides a
PFLobbyJoinLobbyCompletedStateChange.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyGetSearchProperty
5/24/2022 • 2 minutes to read • Edit Online

Get the search property value from its key.

Syntax
HRESULT PFLobbyGetSearchProperty(
PFLobbyHandle lobby,
const char* key,
const char** value
)

Parameters
lobby PFLobbyHandle

The handle of the lobby.


key char*
is null-terminated
The key of the property.
value char**
library-allocated output, may return nullptr
The output value associated with the key. An output null value signifies the property wasn't present.
Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
Search properties are visible to non-members of the lobby as metadata which can be used to filter and sort
lobby search results.

If this lobby object is still in the process of asynchronously being created or joined via a call to
PFMultiplayerCreateAndJoinLobby() or PFMultiplayerJoinLobby(), this method will return no properties.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyGetSearchPropertyKeys
5/24/2022 • 2 minutes to read • Edit Online

Get the list of search property keys.

Syntax
HRESULT PFLobbyGetSearchPropertyKeys(
PFLobbyHandle lobby,
uint32_t* propertyCount,
const char* const** keys
)

Parameters
lobby PFLobbyHandle

The handle of the lobby.


propertyCount uint32_t*
output
The output count of search properties.
keys char* const**
library-allocated output array of size *propertyCount

The output array of search property keys.


Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
Search properties are visible to non-members of the lobby as metadata which can be used to filter and sort
lobby search results.

If this lobby object is still in the process of asynchronously being created or joined via a call to
PFMultiplayerCreateAndJoinLobby() or PFMultiplayerJoinLobby(), this method will return no keys.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyLeave
5/24/2022 • 2 minutes to read • Edit Online

Request one or all local users to leave the lobby.

Syntax
HRESULT PFLobbyLeave(
PFLobbyHandle lobby,
const PFEntityKey* localUser,
void* asyncContext
)

Parameters
lobby PFLobbyHandle

The handle of the lobby.


localUser PFEntityKey*
optional
An optional value to indicate if a specific local user should leave the lobby. If this value is nullptr, all local users
will leave the lobby.
asyncContext void*
optional
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
This method queues an asynchronous operation to remove one or all local users from the lobby. On completion,
a PFLobbyLeaveLobbyCompletedStateChange will be provided indicating that the operation has completed.

This method does not guarantee the leave will succeed. The operation may fail due to networking or service
errors. If the leave attempt fails but is retriable, the library will continue to retry the leave operation. Otherwise,
the local client will disconnect the requested local members from the lobby, but leave them as members. They
will remain as disconnected members until they rejoin.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyPostUpdate
5/24/2022 • 2 minutes to read • Edit Online

Post an update to the lobby.

Syntax
HRESULT PFLobbyPostUpdate(
PFLobbyHandle lobby,
const PFEntityKey* localUser,
const PFLobbyDataUpdate* lobbyUpdate,
const PFLobbyMemberDataUpdate* memberUpdate,
void* asyncContext
)

Parameters
lobby PFLobbyHandle

The handle of the lobby.


localUser PFEntityKey*
The local user posting the update.
lobbyUpdate PFLobbyDataUpdate*
optional
An optional update to apply to the shared portion of the lobby on behalf of localUser . If this is not provided,
memberUpdate must be provided.

memberUpdate PFLobbyMemberDataUpdate*
optional
An optional update to apply to the portion of the lobby owned by localUser . If this is not provided,
lobbyUpdate must be provided.

asyncContext void*
optional
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
This is an asynchronous operation. Upon successful completion, the title will be provided a
PFLobbyPostUpdateCompletedStateChange with the PFLobbyPostUpdateCompletedStateChange::result field set
to S_OK . Upon a failed completion, the title will be provided a PFLobbyPostUpdateCompletedStateChange with
the PFLobbyPostUpdateCompletedStateChange::result field set to a failure. If applying the update would change
the state of the lobby, the title will be provided a PFLobbyUpdatedStateChange sometime afterwards.

This operation completing successfully only indicates that the Lobby service has accepted the update. The title's
local view of the Lobby state will not reflect this update until a PFLobbyUpdatedStateChange is provided to the
title with the updated state.

The lobbyUpdate contains fields that can only be modified by the owner of the lobby. This method will return an
error if one of those fields is specified and localUser is not the owner of the lobby.

If both a lobbyUpdate and memberUpdate are supplied to this method on behalf of a single entity, both updates
will happen atomically.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbySendInvite
5/24/2022 • 2 minutes to read • Edit Online

Send an invite to this lobby from the local user to the invited entity.

Syntax
HRESULT PFLobbySendInvite(
PFLobbyHandle lobby,
const PFEntityKey* sender,
const PFEntityKey* invitee,
void* asyncContext
)

Parameters
lobby PFLobbyHandle

The handle of the lobby.


sender PFEntityKey*
The local user sending the invite.
invitee PFEntityKey*
The invited entity.
asyncContext void*
optional
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
This is an asynchronous operation. Upon successful completion, the title will be provided a
PFLobbySendInviteCompletedStateChange with the PFLobbySendInviteCompletedStateChange::result field set
to S_OK . Upon a failed completion, the title will be provided a PFLobbySendInviteCompletedStateChange with
the PFLobbySendInviteCompletedStateChange::result field set to a failure.

The sender must be a local user of this lobby which joined from this client.

Requirements
Header : PFLobby.h
See also
PFLobby members
PFLobbySetCustomContext
5/24/2022 • 2 minutes to read • Edit Online

Configures an optional, custom pointer-sized context value with this lobby object.

Syntax
HRESULT PFLobbySetCustomContext(
PFLobbyHandle lobby,
void* customContext
)

Parameters
lobby PFLobbyHandle

The handle of the lobby.


customContext void*
optional
An arbitrary, pointer-sized value to store with the player object.
Return value
Type: HRESULT
S_OK if configuring the custom context succeeded or an error code otherwise. The human-readable form of the
error code can be retrieved via PFMultiplayerGetErrorMessage().

Remarks
The custom context is typically used as a "shortcut" that simplifies accessing local, title-specific memory
associated with the lobby without requiring a mapping lookup. The value is retrieved using the
PFLobbyGetCustomContext() method.

Any configured value is treated as opaque by the library, and is only valid on the local device; it is not
transmitted over the network.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyGetCustomContext
PFMultiplayerCreateAndJoinLobby
5/24/2022 • 2 minutes to read • Edit Online

Create a new lobby and add the creating PlayFab entity to it.

Syntax
HRESULT PFMultiplayerCreateAndJoinLobby(
PFMultiplayerHandle handle,
const PFEntityKey* creator,
const PFLobbyCreateConfiguration* createConfiguration,
const PFLobbyJoinConfiguration* joinConfiguration,
void* asyncContext,
PFLobbyHandle* lobby
)

Parameters
handle PFMultiplayerHandle

The handle of the PFMultiplayer API instance.


creator PFEntityKey*
The local PlayFab entity creating the lobby.
createConfiguration PFLobbyCreateConfiguration*
The initial configuration data used when creating the lobby.
joinConfiguration PFLobbyJoinConfiguration*
The initial configuration data for the member creating and joining the lobby.
asyncContext void*
optional
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
lobby PFLobbyHandle*
optional, library-allocated output
The optional, output lobby object which can be used to queue operations for immediate execution of this
operation completes.
Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
This is an asynchronous operation. Upon successful completion, the title will be provided a
PFLobbyMemberAddedStateChange followed by a PFLobbyCreateAndJoinLobbyCompletedStateChange with
the PFLobbyCreateAndJoinLobbyCompletedStateChange::result field set to S_OK . Upon a failed completion, the
title will be provided a PFLobbyCreateAndJoinLobbyCompletedStateChange with the
PFLobbyCreateAndJoinLobbyCompletedStateChange::result field set to a failure.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFMultiplayerFindLobbies
5/24/2022 • 2 minutes to read • Edit Online

Search for lobbies on behalf of the local user.

Syntax
HRESULT PFMultiplayerFindLobbies(
PFMultiplayerHandle handle,
const PFEntityKey* searchingEntity,
const PFLobbySearchConfiguration* searchConfiguration,
void* asyncContext
)

Parameters
handle PFMultiplayerHandle

The handle of the PFMultiplayer API instance.


searchingEntity PFEntityKey*
The playfab entity performing the search.
searchConfiguration PFLobbySearchConfiguration*
The configuration used to filter and sort the searched lobbies.
asyncContext void*
optional
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
This is an asynchronous operation. Upon successful completion, the title will be provided a
PFLobbyFindLobbiesCompletedStateChange with the PFLobbyFindLobbiesCompletedStateChange::result field
set to S_OK . Upon a failed completion, the title will be provided a PFLobbyFindLobbiesCompletedStateChange
with the PFLobbyFindLobbiesCompletedStateChange::result field set to a failure.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFMultiplayerFinishProcessingLobbyStateChanges
5/24/2022 • 2 minutes to read • Edit Online

Returns an array of PFLobbyStateChanges that were being processed.

Syntax
HRESULT PFMultiplayerFinishProcessingLobbyStateChanges(
PFMultiplayerHandle handle,
uint32_t stateChangeCount,
const PFLobbyStateChange* const* stateChanges
)

Parameters
handle PFMultiplayerHandle

The handle of the PFMultiplayer API instance.


stateChangeCount uint32_t
The number of changes, provided in the list specified by stateChanges , previously returned by
PFMultiplayerStartProcessingLobbyStateChanges() that have now been handled by the title.
stateChanges PFLobbyStateChange* const*
input array of size stateChangeCount
The array of changes previously returned by PFMultiplayerStartProcessingLobbyStateChanges() that have now
been handled by the title.
Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
This method informs the Lobby library that the state changes reported by a previous call to
PFMultiplayerStartProcessingLobbyStateChanges() have now been handled by the title, so their associated
resources can be reclaimed. You may call PFMultiplayerFinishProcessingLobbyStateChanges() with any number
of state changes. Each state change returned by PFMultiplayerStartProcessingLobbyStateChanges() must be
returned to PFMultiplayerFinishProcessingLobbyStateChanges() exactly once, but may be returned out of order
and may be interleaved with state changes from other calls to
PFMultiplayerStartProcessingLobbyStateChanges().

Any resources associated with a specific state change are guaranteed to stay valid until the state change is
returned to PFMultiplayerFinishProcessingLobbyStateChanges().

For best results, you should minimize the time you spend handling state changes before calling
PFMultiplayerFinishProcessingLobbyStateChanges().
Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyStateChange
PFMultiplayerStartProcessingLobbyStateChanges
PFMultiplayerGetLobbyInviteListenerStatus
5/24/2022 • 2 minutes to read • Edit Online

Retrieve the status of the entity's invite listener.

Syntax
HRESULT PFMultiplayerGetLobbyInviteListenerStatus(
PFMultiplayerHandle handle,
const PFEntityKey* listeningEntity,
PFLobbyInviteListenerStatus* status
)

Parameters
handle PFMultiplayerHandle

The handle of the PFMultiplayer API instance.


listeningEntity PFEntityKey*
The entity which is listening for invites.
status PFLobbyInviteListenerStatus*
output
The output status value.
Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
This value is used to understand the state of an entity's invite listener. If the invite listener encounters a fatal
error, non-fatal error, or diagnostic change, the listener's status value will reflect it.

When the invite listener's status changes, a PFLobbyInviteListenerStatusChangedStateChange struct will be


provided by PFMultiplayerStartProcessingLobbyStateChanges. This method can then be called to retrieve the
latest status and act accordingly.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFMultiplayerJoinArrangedLobby
5/24/2022 • 2 minutes to read • Edit Online

Joins a lobby using an arrangement string provided by another service, such as matchmaking. If no one has
joined the lobby yet, the lobby is initialized using the configuration parameters.

Syntax
HRESULT PFMultiplayerJoinArrangedLobby(
PFMultiplayerHandle handle,
const PFEntityKey* newMember,
const char* arrangementString,
const PFLobbyArrangedJoinConfiguration* configuration,
void* asyncContext,
PFLobbyHandle* lobby
)

Parameters
handle PFMultiplayerHandle

The handle of the PFMultiplayer API instance.


newMember PFEntityKey*
The local PlayFab entity joining the lobby.
arrangementString char*
is null-terminated
The arrangement string used by the entity to join the lobby.
configuration PFLobbyArrangedJoinConfiguration*
The initial configuration data used to initialize the lobby, if no one has joined the lobby yet.
asyncContext void*
optional
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
lobby PFLobbyHandle*
optional, library-allocated output
The optional, output lobby object which can be used to queue operations for immediate execution of this
operation completes.
Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
This is an asynchronous operation. Upon successful completion, the title will be provided a
PFLobbyMemberAddedStateChange followed by a PFLobbyJoinArrangedLobbyCompletedStateChange with the
PFLobbyJoinArrangedLobbyCompletedStateChange::result field set to S_OK . Upon a failed completion, the title
will be provided a PFLobbyJoinArrangedLobbyCompletedStateChange with the
PFLobbyJoinArrangedLobbyCompletedStateChange::result field set to a failure.

When using matchmaking through this library, the PFMatchmakingMatchDetails::lobbyArrangementString can


be used with this method to join a lobby with all of the users that have been matched together.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFMultiplayerJoinLobby
5/24/2022 • 2 minutes to read • Edit Online

Join a lobby as the local PlayFab entity.

Syntax
HRESULT PFMultiplayerJoinLobby(
PFMultiplayerHandle handle,
const PFEntityKey* newMember,
const char* connectionString,
const PFLobbyJoinConfiguration* configuration,
void* asyncContext,
PFLobbyHandle* lobby
)

Parameters
handle PFMultiplayerHandle

The handle of the PFMultiplayer API instance.


newMember PFEntityKey*
The local entity joining the lobby.
connectionString char*
is null-terminated
The connection string used by the entity to join the lobby.
configuration PFLobbyJoinConfiguration*
The initial configuration data used when joining the lobby.
asyncContext void*
optional
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
lobby PFLobbyHandle*
optional, library-allocated output
The optional, output lobby object which can be used to queue operations for immediate execution of this
operation completes.
Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
This is an asynchronous operation. Upon successful completion, the title will be provided a
PFLobbyMemberAddedStateChange followed by a PFLobbyUpdatedStateChange and
PFLobbyJoinLobbyCompletedStateChange with the PFLobbyJoinLobbyCompletedStateChange::result field set to
S_OK . Upon a failed completion, the title will be provided a PFLobbyJoinLobbyCompletedStateChange with the
PFLobbyJoinLobbyCompletedStateChange::result field set to a failure.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFMultiplayerStartListeningForLobbyInvites
5/24/2022 • 2 minutes to read • Edit Online

Enables the Lobby invite listener for a given entity.

Syntax
HRESULT PFMultiplayerStartListeningForLobbyInvites(
PFMultiplayerHandle handle,
const PFEntityKey* listeningEntity
)

Parameters
handle PFMultiplayerHandle

The handle of the PFMultiplayer API instance.


listeningEntity PFEntityKey*
The entity which will listen for invites.
Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
This operation will synchronously start listening for invites on behalf of the provided entity. When invites are
received, they will be provided via PFLobbyInviteReceivedStateChange structs. When the status of the invite
listener changes, notifications will be provided via PFLobbyInviteListenerStatusChangedStateChange structs.

Only invites sent after the listener has been started will be received on this client. Invites sent while this listener
is not active will not be queued.

Invite listening is, by default, disabled for all entities. This method should be called for each local entity that the
title wants to receive Lobby invites.

Lobby invites and this invite listener are unrelated to and unaffected by platform invite mechanisms.

This method may only be called if the Lobby invite listener is not already enabled for the given entity.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFMultiplayerStartProcessingLobbyStateChanges
5/24/2022 • 2 minutes to read • Edit Online

Retrieves an array of all PFLobbyStateChanges to process since the last such call.

Syntax
HRESULT PFMultiplayerStartProcessingLobbyStateChanges(
PFMultiplayerHandle handle,
uint32_t* stateChangeCount,
const PFLobbyStateChange* const** stateChanges
)

Parameters
handle PFMultiplayerHandle

The handle of the PFMultiplayer API instance.


stateChangeCount uint32_t*
output
The output number of PFLobbyStateChange entries for the title to handle in the stateChanges array.
stateChanges PFLobbyStateChange* const**
library-allocated output array of size *stateChangeCount
A library-allocated output array of all PFLobbyStateChange entries for the title to handle and then pass to
PFMultiplayerFinishProcessingLobbyStateChanges().
Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
This method provides the Lobby library an opportunity to synchronize state with remote devices or services,
and retrieves a list of all changes currently available for the title since the last call to this method. The title should
use the provided array of 0 or more changes to update its own state or UI, and then call
PFMultiplayerFinishProcessingLobbyStateChanges() with them in a timely manner.

Lobby library state exposed by the library can change during this call, so you must be thread-safe in your use of
it. For example, invoking PFMultiplayerStartProcessingLobbyStateChanges() on your UI thread at the same time
a separate worker thread is looping through the list of lobby members returned by PFLobbyGetMembers() may
result in crashes because PFMultiplayerStartProcessingLobbyStateChanges() can alter the memory associated
with the member list. PFMultiplayerStartProcessingLobbyStateChanges() should be called frequently-- at least
once per graphics frame. It's designed to execute and return quickly such that it can be called on your main UI
thread with negligible impact. For best results, you should also minimize the time you spend handling state
changes before calling PFMultiplayerFinishProcessingLobbyStateChanges().
Each state change returned by PFMultiplayerStartProcessingLobbyStateChanges() must be returned to
PFMultiplayerFinishProcessingLobbyStateChanges() exactly once, but may be returned out of order and may be
interleaved with state changes from other calls to PFMultiplayerStartProcessingLobbyStateChanges(). Any
resources associated with a specific state change are guaranteed to stay valid until the state change is returned
to PFMultiplayerFinishProcessingLobbyStateChanges().

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyStateChange
PFMultiplayerFinishProcessingLobbyStateChanges
PFMultiplayerStopListeningForLobbyInvites
5/24/2022 • 2 minutes to read • Edit Online

Disables the Lobby invite listener for a given entity.

Syntax
HRESULT PFMultiplayerStopListeningForLobbyInvites(
PFMultiplayerHandle handle,
const PFEntityKey* listeningEntity
)

Parameters
handle PFMultiplayerHandle

The handle of the PFMultiplayer API instance.


listeningEntity PFEntityKey*
The entity which is listening for invites.
Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
This operation will synchronously stop listening for invites on behalf of the provided entity.

Invite notifications which have already been queued internally will still be provided via the next call to
PFMultiplayerStartProcessingLobbyStateChanges().

Lobby invites and this invite listener are unrelated to and unaffected by platform invite mechanisms.

This method may only be called if the Lobby invite listener is already enabled for the given entity.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFMatchmakingTicketCancel
5/24/2022 • 2 minutes to read • Edit Online

Cancels the ticket.

Syntax
HRESULT PFMatchmakingTicketCancel(
PFMatchmakingTicketHandle ticket
)

Parameters
ticket PFMatchmakingTicketHandle

The handle of the matchmaking ticket.


Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
This method queues an asynchronous operation to cancel this matchmaking ticket. On success, a
PFMatchmakingTicketCompletedStateChange will be provided indicating that the ticket has been canceled.

This method does not guarantee the ticket will be canceled. The ticket may complete before the cancelation can
be processed, or the cancelation request may fail due to networking or service errors. If the cancelation attempt
fails but is retriable, the library will continue to retry the cancelation. Otherwise, a
PFMatchmakingTicketCompletedStateChange will be provided that indicates the ticket failed.

Requirements
Header : PFMatchmaking.h

See also
PFMatchmaking members
PFMatchmakingTicketGetMatch
5/24/2022 • 2 minutes to read • Edit Online

Provides the match, if one has been found.

Syntax
HRESULT PFMatchmakingTicketGetMatch(
PFMatchmakingTicketHandle ticket,
const PFMatchmakingMatchDetails** match
)

Parameters
ticket PFMatchmakingTicketHandle

The handle of the matchmaking ticket.


match PFMatchmakingMatchDetails**
library-allocated output
The match that was found.
Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
This method will fail if the ticket isn't in the PFMatchmakingTicketStatus::Matched state. The ticket state can be
retrieved via PFMatchmakingTicketGetStatus.

Requirements
Header : PFMatchmaking.h

See also
PFMatchmaking members
PFMatchmakingTicketGetStatus
5/24/2022 • 2 minutes to read • Edit Online

Provides the matchmaking ticket status.

Syntax
HRESULT PFMatchmakingTicketGetStatus(
PFMatchmakingTicketHandle ticket,
PFMatchmakingTicketStatus* status
)

Parameters
ticket PFMatchmakingTicketHandle

TBD
status PFMatchmakingTicketStatus*
output
The matchmaking ticket status.
Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Requirements
Header : PFMatchmaking.h

See also
PFMatchmaking members
PFMatchmakingTicketGetTicketId
5/24/2022 • 2 minutes to read • Edit Online

Provides the ticket ID.

Syntax
HRESULT PFMatchmakingTicketGetTicketId(
PFMatchmakingTicketHandle ticket,
const char** id
)

Parameters
ticket PFMatchmakingTicketHandle

The handle of the matchmaking ticket.


id char**
library-allocated output
The ticket ID.
Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
The ticket ID will be an empty string if the ticket is in the PFMatchmakingTicketStatus::Creating state or if the
ticket is in the PFMatchmakingTicketStatus::Failed state due to failure to submit a ticket to the matchmaking
service. The ticket state can be retrieved via PFMatchmakingTicketGetStatus.

Requirements
Header : PFMatchmaking.h

See also
PFMatchmaking members
PFMultiplayerCreateMatchmakingTicket
5/24/2022 • 2 minutes to read • Edit Online

Creates a matchmaking ticket for one or more local users.

Syntax
HRESULT PFMultiplayerCreateMatchmakingTicket(
PFMultiplayerHandle handle,
uint32_t localUserCount,
const PFEntityKey* localUsers,
const char* const* localUserAttributes,
const PFMatchmakingTicketConfiguration* configuration,
void* asyncContext,
PFMatchmakingTicketHandle* ticket
)

Parameters
handle PFMultiplayerHandle

The handle of the PFMultiplayer API instance.


localUserCount uint32_t
The count of local users to include in the ticket.
localUsers PFEntityKey*
input array of size localUserCount
The array of local users to include in the ticket.
localUserAttributes char* const*
input array of size localUserCount

The array of local user attribute strings. There should be one attribute string for each local user. Each attribute
string should either be an empty string or a serialized JSON object. For example,
{"player_color":"blue","player_role":"tank"} .

configuration PFMatchmakingTicketConfiguration*
The ticket configuration.
asyncContext void*
optional
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
ticket PFMatchmakingTicketHandle*
library-allocated output
The resulting ticket object.
Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
The library automatically, and asynchronously, will submit all local users on a ticket to the matchmaking service.
Each time the ticket status changes, a PFMatchmakingTicketStatusChangedStateChange will be provided. The
ticket status can be quered at any time via PFMatchmakingTicketGetStatus(). The ticket immediately starts in the
PFMatchmakingTicketStatus::Creating state.

When the ticket has completed, a PFMatchmakingTicketStatusChangedStateChange will be provided. At that


point, a match will have been found or the ticket stopped due to failure. On success, the match that was found
can be queried via PFMatchmakingTicketGetMatch().

All existing tickets in which a local user is a member will be canceled as part of this operation.

A match can't be found until all remote users specified in the membersToMatchWith field of the configuration
parameter have joined the ticket via PFMultiplayerJoinMatchmakingTicketFromId().

Requirements
Header : PFMatchmaking.h

See also
PFMatchmaking members
PFMultiplayerDestroyMatchmakingTicket
5/24/2022 • 2 minutes to read • Edit Online

Destroys the matchmaking ticket.

Syntax
HRESULT PFMultiplayerDestroyMatchmakingTicket(
PFMultiplayerHandle handle,
PFMatchmakingTicketHandle ticket
)

Parameters
handle PFMultiplayerHandle

The handle of the PFMultiplayer API instance.


ticket PFMatchmakingTicketHandle
The ticket to destroy.
Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
This method destroys the matchmaking ticket and reclaims local resources associated with it. If the ticket has not
yet completed, a background operation will perform a single best-effort attempt to cancel the ticket with the
matchmaking service.

Requirements
Header : PFMatchmaking.h

See also
PFMatchmaking members
PFMultiplayerFinishProcessingMatchmakingStateChanges
5/24/2022 • 2 minutes to read • Edit Online

Returns an array of matchmaking state changes that were being processed.

Syntax
HRESULT PFMultiplayerFinishProcessingMatchmakingStateChanges(
PFMultiplayerHandle handle,
uint32_t stateChangeCount,
const PFMatchmakingStateChange* const* stateChanges
)

Parameters
handle PFMultiplayerHandle

The handle of the PFMultiplayer API instance.


stateChangeCount uint32_t
The number of changes, provided in the list specified by stateChanges , previously returned by
PFMultiplayerStartProcessingMatchmakingStateChanges() that have now been handled by the title.
stateChanges PFMatchmakingStateChange* const*
input array of size stateChangeCount
The array of changes previously returned by PFMultiplayerStartProcessingMatchmakingStateChanges() that
have now been handled by the title.
Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
This method informs the Matchmaking library that the state changes reported by a previous call to
PFMultiplayerStartProcessingMatchmakingStateChanges() have now been handled by the title, so their
associated resources can be reclaimed. You may call PFMultiplayerFinishProcessingMatchmakingStateChanges()
with any number of state changes. Each state change returned by
PFMultiplayerStartProcessingMatchmakingStateChanges() must be returned to
PFMultiplayerFinishProcessingMatchmakingStateChanges() exactly once, but may be returned out of order and
may be interleaved with state changes from other calls to
PFMultiplayerStartProcessingMatchmakingStateChanges().

Any resources associated with a specific state change are guaranteed to stay valid until the state change is
returned to PFMultiplayerFinishProcessingMatchmakingStateChanges().

For best results, you should minimize the time you spend handling state changes before calling
PFMultiplayerFinishProcessingMatchmakingStateChanges().
Requirements
Header : PFMatchmaking.h

See also
PFMatchmaking members
PFMatchmakingStateChange
PFMultiplayerStartProcessingMatchmakingStateChanges
PFMultiplayerJoinMatchmakingTicketFromId
5/24/2022 • 2 minutes to read • Edit Online

Joins one or more multiple local users to a matchmaking ticket using a ticket ID and queue name.

Syntax
HRESULT PFMultiplayerJoinMatchmakingTicketFromId(
PFMultiplayerHandle handle,
uint32_t localUserCount,
const PFEntityKey* localUsers,
const char* localUserAttributes,
const char* ticketId,
const char* queueName,
void* asyncContext,
PFMatchmakingTicketHandle* ticket
)

Parameters
handle PFMultiplayerHandle

The handle of the PFMultiplayer API instance.


localUserCount uint32_t
The count of local users to join the ticket.
localUsers PFEntityKey*
input array of size localUserCount
The array of local users to join to the ticket.
localUserAttributes char*
input array of size localUserCount

The array of local user attribute strings. There should be one attribute string for each local user. Each attribute
string should either be an empty string or a serialized JSON object. For example,
{"player_color":"blue","player_role":"tank"} .

ticketId char*
is null-terminated
The ID of the ticket to join.
queueName char*
is null-terminated
The queue to which the ticket belongs.
asyncContext void*
optional
An optional, app-defined, pointer-sized context value that can be used to associate the completion state change
with this call.
ticket PFMatchmakingTicketHandle*
library-allocated output
The resulting ticket object.
Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
The library automatically, and asynchronously, will submit all local users to join the ticket on the matchmaking
service. Each time the ticket status changes, a PFMatchmakingTicketStatusChangedStateChange will be
provided. The ticket status can be quered at any time via PFMatchmakingTicketGetStatus(). The ticket
immediately starts in the PFMatchmakingTicketStatus::Joining state.

When the ticket has completed, a PFMatchmakingTicketStatusChangedStateChange will be provided. At that


point, a match will have been found or the ticket stopped due to failure. On success, the match that was found
can be queried via PFMatchmakingTicketGetMatch().

All existing tickets in which a local user is a member will be canceled as part of this operation.

Requirements
Header : PFMatchmaking.h

See also
PFMatchmaking members
PFMultiplayerStartProcessingMatchmakingStateChanges
5/24/2022 • 2 minutes to read • Edit Online

Retrieves an array of all matchmaking state changes to process since the last such call.

Syntax
HRESULT PFMultiplayerStartProcessingMatchmakingStateChanges(
PFMultiplayerHandle handle,
uint32_t* stateChangeCount,
const PFMatchmakingStateChange* const** stateChanges
)

Parameters
handle PFMultiplayerHandle

The handle of the PFMultiplayer API instance.


stateChangeCount uint32_t*
output
The output number of PFMatchmakingStateChange entries for the title to handle in the stateChanges array.
stateChanges PFMatchmakingStateChange* const**
library-allocated output array of size *stateChangeCount
A library-allocated output array of all PFMatchmakingStateChange entries for the title to handle and then pass
to PFMultiplayerFinishProcessingMatchmakingStateChanges().
Return value
Type: HRESULT
S_OK if the call succeeded or an error code otherwise. The human-readable form of the error code can be
retrieved via PFMultiplayerGetErrorMessage().

Remarks
This method provides the Matchmaking library an opportunity to synchronize state with remote devices or
services, and retrieves a list of all changes currently available for the title since the last call to this method. The
title should use the provided array of 0 or more changes to update its own state or UI, and then call
PFMultiplayerFinishProcessingMatchmakingStateChanges() with them in a timely manner.

Matchmaking library state exposed by the library can change during this call, so you must be thread-safe in
your use of it. PFMultiplayerStartProcessingMatchmakingStateChanges() should be called frequently-- at least
once per graphics frame. It's designed to execute and return quickly such that it can be called on your main UI
thread with negligible impact. For best results, you should also minimize the time you spend handling state
changes before calling PFMultiplayerFinishProcessingMatchmakingStateChanges().

Each state change returned by PFMultiplayerStartProcessingMatchmakingStateChanges() must be returned to


PFMultiplayerFinishProcessingMatchmakingStateChanges() exactly once, but may be returned out of order and
may be interleaved with state changes from other calls to
PFMultiplayerStartProcessingMatchmakingStateChanges(). Any resources associated with a specific state
change are guaranteed to stay valid until the state change is returned to
PFMultiplayerFinishProcessingMatchmakingStateChanges().

Requirements
Header : PFMatchmaking.h

See also
PFMatchmaking members
PFMatchmakingStateChange
PFMultiplayerFinishProcessingMatchmakingStateChanges
PFMultiplayerThreadId
5/24/2022 • 2 minutes to read • Edit Online

Threads that Multiplayer library uses for internal purposes.

Syntax
enum class PFMultiplayerThreadId : uint32_t
{
Networking = 0,
}

Constants
C O N STA N T DESC RIP T IO N

Networking Represents Multiplayer library internal networking threads

Requirements
Header : PFMultiplayer.h

See also
PFMultiplayer members
PFMultiplayerSetThreadAffinityMask
PFLobbyAccessPolicy
5/24/2022 • 2 minutes to read • Edit Online

Values representing the lobby's access policy.

Syntax
enum class PFLobbyAccessPolicy : uint32_t
{
Public = 0,
Friends = 1,
Private = 2,
}

Constants
C O N STA N T DESC RIP T IO N

Public The lobby is both visible in queries and any player may join,
including invited players.

Friends The lobby and its connection string are queryable by friends
of members in this lobby.

In some multiplayer social networks, friendship is a


unidirectional relationship. One user may "follow" another or
be their friend, but the same is not necessarily true in the
reverse direction. This access policy only grants access when
a bidirectional friendship exists. That is, the user querying for
the lobby and the user in the lobby must both be friends
with each other.

When querying for lobbies, users can opt into searching


external multiplayer social networks for friendship
relationships as well as the native PlayFab friends list. For
example, a user could opt to check their Xbox Live friends list
in addition to the PlayFab friends list. An external multiplayer
social relationship can only be considered if both PlayFab
users for this title have linked that mulitplayer social network
to their PlayFab accounts.

Private The lobby is not visible in queries, and a player must receive
an invite to join.

Remarks
The access policy controls whether this lobby's connection string is accessible in search queries.

Requirements
Header : PFLobby.h
See also
PFLobby members
PFLobbyDisconnectingReason
5/24/2022 • 2 minutes to read • Edit Online

Reasons the client no longer has access to the Lobby.

Syntax
enum class PFLobbyDisconnectingReason : uint32_t
{
NoLocalMembers = 0,
LobbyDeleted = 1,
ConnectionInterruption = 2,
}

Constants
C O N STA N T DESC RIP T IO N

NoLocalMembers The client is no longer connected to the lobby because none


of the client's local entities are members.

LobbyDeleted The client is being disconnected from the lobby because the
lobby's server owner has deleted the lobby.

ConnectionInterruption The client is being disconnected from the lobby because the
client has lost connection.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyInviteListenerStatus
5/24/2022 • 2 minutes to read • Edit Online

Values representing the current status of an invite listener.

Syntax
enum class PFLobbyInviteListenerStatus : uint32_t
{
NotListening = 0,
Listening = 1,
NotAuthorized = 2,
}

Constants
C O N STA N T DESC RIP T IO N

NotListening The invite listener has not been started or has been stopped
and is not listening for invites.

Listening The invite listener has been established and is listening for
invites.

NotAuthorized The listening entity was not authorized to establish an invite


listener.

This status is fatal. The title should clear the invite listener
with PFMultiplayerStopListeningForLobbyInvites. No invites
will be received on the corresponding listener after this
status update.

Receiving this status likely represents a programming error


where an invalid entity has been passed to
PFMultiplayerStopListeningForLobbyInvites .

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyMemberRemovedReason
5/24/2022 • 2 minutes to read • Edit Online

Reasons why a member was removed from a lobby.

Syntax
enum class PFLobbyMemberRemovedReason : uint32_t
{
LocalUserLeftLobby = 0,
LocalUserForciblyRemoved = 1,
RemoteUserLeftLobby = 2,
}

Constants
C O N STA N T DESC RIP T IO N

LocalUserLeftLobby The local user is being removed because the title called
PFLobbyLeave().

LocalUserForciblyRemoved The local user entity was forcibly removed by the owner.

RemoteUserLeftLobby The remote user has been removed from the lobby. It is
unspecified whether they left voluntarily or if they were
forcibly removed by the owner.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyMembershipLock
5/24/2022 • 2 minutes to read • Edit Online

Values representing the state of the lobby's membership lock.

Syntax
enum class PFLobbyMembershipLock : uint32_t
{
Unlocked = 0,
Locked = 1,
}

Constants
C O N STA N T DESC RIP T IO N

Unlocked Lobby membership is unlocked. New members will not be


prevented from joining.

Locked Lobby membership is locked. New members will be


prevented from joining.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyOwnerMigrationPolicy
5/24/2022 • 2 minutes to read • Edit Online

The available policies the lobby service can use to migrate lobby ownership between members.

Syntax
enum class PFLobbyOwnerMigrationPolicy : uint32_t
{
Automatic = 0,
Manual = 1,
None = 2,
Server = 3,
}

Constants
C O N STA N T DESC RIP T IO N

Automatic Once the lobby owner is disconnected, a new owner is


chosen at random from the set of connected members.

Manual Once the lobby owner is disconnected, any member may


elect themselves the new owner.

Until a new owner is chosen, PFLobbyGetOwner will return a


null owner.

None At any point, any member may elect themselves the owner
of the lobby, regardless of the state of the current owner.

If the current owner leaves, PFLobbyGetOwner will return a


null owner until a new owner elects themselves.

Server The server is the owner and owner migration is not possible.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyStateChangeType
5/24/2022 • 2 minutes to read • Edit Online

The types of state changes that can occur.

Syntax
enum class PFLobbyStateChangeType : uint32_t
{
CreateAndJoinLobbyCompleted = 0,
JoinLobbyCompleted = 1,
MemberAdded = 2,
AddMemberCompleted = 3,
MemberRemoved = 4,
ForceRemoveMemberCompleted = 5,
LeaveLobbyCompleted = 6,
Updated = 7,
PostUpdateCompleted = 8,
Disconnecting = 9,
Disconnected = 10,
JoinArrangedLobbyCompleted = 11,
FindLobbiesCompleted = 12,
InviteReceived = 13,
InviteListenerStatusChanged = 14,
SendInviteCompleted = 15,
}

Constants
C O N STA N T DESC RIP T IO N

CreateAndJoinLobbyCompleted The operation started by a previous call to


PFMultiplayerCreateAndJoinLobby() completed.

The PFLobbyStateChange object should be cast to a


PFLobbyCreateAndJoinLobbyCompletedStateChange object
for more information.

JoinLobbyCompleted The operation started by a previous call to


PFMultiplayerJoinLobby() completed.

The PFLobbyStateChange object should be cast to a


PFLobbyJoinLobbyCompletedStateChange object for more
information.

MemberAdded A PlayFab entity was added to a lobby as a member.

The PFLobbyStateChange object should be cast to a


PFLobbyMemberAddedStateChange object for more
information.
C O N STA N T DESC RIP T IO N

AddMemberCompleted The operation started by a previous call to


PFLobbyAddMember() completed.

The PFLobbyStateChange object should be cast to a


PFLobbyAddMemberCompletedStateChange object for more
information.

MemberRemoved A PlayFab entity was removed from a lobby as a member.

The PFLobbyStateChange object should be cast to a


PFLobbyMemberRemovedStateChange object for more
information.

ForceRemoveMemberCompleted The operation started by a previous call to


PFLobbyForceRemoveMember() completed.

The PFLobbyStateChange object should be cast to a


PFLobbyForceRemoveMemberCompletedStateChange object
for more information.

LeaveLobbyCompleted The operation started by a previous call to PFLobbyLeave()


completed.

The PFLobbyStateChange object should be cast to a


PFLobbyLeaveLobbyCompletedStateChange object for more
information.

Updated A lobby was updated.

The PFLobbyStateChange object should be cast to a


PFLobbyUpdatedStateChange object for more information.

PostUpdateCompleted The operation started by a previous call to


PFLobbyPostUpdate() completed.

The PFLobbyStateChange object should be cast to a


PFLobbyPostUpdateCompletedStateChange object for more
information.

This operation completing only indicates whether the Lobby


service has accepted the update or not. The title's local view
of the Lobby state will not reflect this update until a
PFLobbyUpdatedStateChange is provided to the title with
the updated state.

Disconnecting The client has started disconnecting from a lobby.

The PFLobbyStateChange object should be cast to a


PFLobbyDisconnectingStateChange object for more
information.

Disconnected The client has disconnected from a lobby.

The PFLobbyStateChange object should be cast to a


PFLobbyDisconnectedStateChange object for more
information.
C O N STA N T DESC RIP T IO N

JoinArrangedLobbyCompleted The operation started by a previous call to


PFMultiplayerJoinArrangedLobby() completed.

The PFLobbyStateChange object should be cast to a


PFLobbyJoinArrangedLobbyCompletedStateChange object
for more information.

FindLobbiesCompleted The operation started by a previous call to


PFMultiplayerFindLobbies() completed.

The PFLobbyStateChange object should be cast to a


PFLobbyFindLobbiesCompletedStateChange object for more
information.

InviteReceived An entity on this client has received an invite to a lobby.

The PFLobbyStateChange object should be cast to a


PFLobbyInviteReceivedStateChange object for more
information.

InviteListenerStatusChanged An invite listener's status has changed.

The PFLobbyStateChange object should be cast to a


PFLobbyInviteListenerStatusChangedStateChange object for
more information.

SendInviteCompleted The operation started by a previous call to


PFLobbySendInvite() completed.

The PFLobbyStateChange object should be cast to a


PFLobbySendInviteCompletedStateChange object for more
information.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFMatchmakingStateChangeType
5/24/2022 • 2 minutes to read • Edit Online

The types of state changes that can occur.

Syntax
enum class PFMatchmakingStateChangeType : uint32_t
{
TicketStatusChanged = 0,
TicketCompleted = 1,
}

Constants
C O N STA N T DESC RIP T IO N

TicketStatusChanged A matchmaking ticket status has changed.

The PFMatchmakingStateChange object should be cast to a


PFMatchmakingTicketStatusChangedStateChange object for
more information.

TicketCompleted A matchmaking ticket has completed.

The PFMatchmakingStateChange object should be cast to a


PFMatchmakingTicketCompletedStateChange object for
more information.

Requirements
Header : PFMatchmaking.h

See also
PFMatchmaking members
PFMatchmakingTicketStatus
5/24/2022 • 2 minutes to read • Edit Online

The possible states for a matchmaking ticket.

Syntax
enum class PFMatchmakingTicketStatus : uint32_t
{
Creating = 0,
Joining = 1,
WaitingForPlayers = 2,
WaitingForMatch = 3,
Matched = 4,
Canceled = 5,
Failed = 6,
}

Constants
C O N STA N T DESC RIP T IO N

Creating The matchmaking ticket is being created.

Joining The matchmaking ticket is being joined.

WaitingForPlayers The matchmaking ticket is waiting for all remote users


specified in the membersToMatchWith field of its
configuration to join the ticket via
PFMultiplayerJoinMatchmakingTicketFromId.

WaitingForMatch The matchmaking ticket is waiting for a match to be found.

Matched The matchmaking ticket has found a match.

Canceled The matchmaking ticket has been canceled.

Failed The matchmaking ticket failed to find a match.

Requirements
Header : PFMatchmaking.h

See also
PFMatchmaking members
PFLobbyArrangedJoinConfiguration
5/24/2022 • 2 minutes to read • Edit Online

The initial configuration data used when joining an arranged lobby.

Syntax
struct PFLobbyArrangedJoinConfiguration {
uint32_t maxMemberCount;
PFLobbyOwnerMigrationPolicy ownerMigrationPolicy;
PFLobbyAccessPolicy accessPolicy;
uint32_t memberPropertyCount;
const char* const* memberPropertyKeys;
const char* const* memberPropertyValues;
}

Members
maxMemberCount uint32_t
The maximum number of members allowed in the lobby, if joiner is the first member in the lobby.
This value must be at least PFLobbyMaxMemberCountLowerLimit and no more than
PFLobbyMaxMemberCountUpperLimit .

If a client would violate this limit by calling PFMultiplayerJoinLobby() or PFLobbyAddMember, the operation will
fail asynchronously.
ownerMigrationPolicy PFLobbyOwnerMigrationPolicy
The owner migration policy for the lobby, if the joiner is the first member in the lobby.
This value cannot be set to PFLobbyOwnerMigrationPolicy::Server .
accessPolicy PFLobbyAccessPolicy
The access policy for the lobby, if the joiner is the first member in the lobby.
memberPropertyCount uint32_t
The number of initial member properties for the joiner of the lobby.
memberPropertyKeys const char* const*
array of size memberPropertyCount

The keys of the initial member properties for the joiner of the lobby.
Per-member properties are only visible to members of the lobby.
memberPropertyValues const char* const*
array of size memberPropertyCount

The values of the initial member properties for the joiner of the lobby.
Per-member properties are only visible to members of the lobby.
Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyCreateConfiguration
5/24/2022 • 2 minutes to read • Edit Online

The initial configuration data used when creating a lobby.

Syntax
struct PFLobbyCreateConfiguration {
uint32_t maxMemberCount;
PFLobbyOwnerMigrationPolicy ownerMigrationPolicy;
PFLobbyAccessPolicy accessPolicy;
uint32_t searchPropertyCount;
const char* const* searchPropertyKeys;
const char* const* searchPropertyValues;
uint32_t lobbyPropertyCount;
const char* const* lobbyPropertyKeys;
const char* const* lobbyPropertyValues;
}

Members
maxMemberCount uint32_t
The maximum number of members allowed in the new lobby.
This value must be at least PFLobbyMaxMemberCountLowerLimit and no more than
PFLobbyMaxMemberCountUpperLimit .

If a client would violate this limit by calling PFMultiplayerJoinLobby() or PFLobbyAddMember, the operation will
fail asynchronously.
ownerMigrationPolicy PFLobbyOwnerMigrationPolicy
The owner migration policy for the new lobby.
This value cannot be set to PFLobbyOwnerMigrationPolicy::Server .
accessPolicy PFLobbyAccessPolicy
The access policy for the new lobby.
searchPropertyCount uint32_t
The number of initial search properties for the new lobby.
searchPropertyKeys const char* const*
array of size searchPropertyCount

The keys of the initial search properties for the new lobby.
Search properties are visible to non-members of the lobby as metadata which can be used to filter and sort
lobby search results.

Search properties must be of the form string_keyN or number_keyN where "N" is a number between 1 and
PFLobbyMaxSearchPropertyCount . e.g. string_key1, number_key14, etc.
searchPropertyValues const char* const*
array of size searchPropertyCount

The values of the initial search properties for the new lobby.
Search properties are visible to non-members of the lobby as metadata which can be used to filter and sort
lobby search results.
lobbyPropertyCount uint32_t
The number of initial lobby properties for the new lobby.
lobbyPropertyKeys const char* const*
array of size lobbyPropertyCount

The keys of the initial lobby properties for the new lobby.
Lobby properties are only visible to members of the lobby.
lobbyPropertyValues const char* const*
array of size lobbyPropertyCount

The values of the initial lobby properties for the new lobby.
Lobby properties are only visible to members of the lobby.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyDataUpdate
5/24/2022 • 3 minutes to read • Edit Online

A request to make an update to the shared portion of the lobby on behalf of a member.

Syntax
struct PFLobbyDataUpdate {
const PFEntityKey* newOwner;
const uint32_t* maxMemberCount;
const PFLobbyAccessPolicy* accessPolicy;
const PFLobbyMembershipLock* membershipLock;
uint32_t searchPropertyCount;
const char* const* searchPropertyKeys;
const char* const* searchPropertyValues;
uint32_t lobbyPropertyCount;
const char* const* lobbyPropertyKeys;
const char* const* lobbyPropertyValues;
}

Members
newOwner const PFEntityKey*
may be nullptr
An optional, new owner of the lobby.
This value can only be updated under one of the following conditions:
The member updating this field is the lobby's current owner
The owner migration policy is PFLobbyOwnerMigrationPolicy::Manual and there is currently no owner
The owner migration policy is PFLobbyOwnerMigrationPolicy::None
maxMemberCount const uint32_t*
may be nullptr
An optional, updated capacity for the number of members in this lobby.
This new value must be greater than than the number of members currently in the lobby and less than
PFLobbyMaxMemberCountUpperLimit .

This value can only be updated by the current lobby owner.


accessPolicy const PFLobbyAccessPolicy*
may be nullptr
An optional, updated access policy for this lobby.
This value can only be updated by the current lobby owner.
membershipLock const PFLobbyMembershipLock*
may be nullptr
An optional update to the membership lock on this lobby.
This value can only be updated by the current lobby owner.
searchPropertyCount uint32_t
The number of search properties to update.
Only the current lobby owner can update the search properties.

There may only be PFLobbyMaxSearchPropertyCount concurrent search properties at any given time. Therefore, at
most, twice that many unique properties can be specified in this update if half of those properties are being
deleted.

If the property limits are violated, the entire update operation will fail.
searchPropertyKeys const char* const*
array of size searchPropertyCount

The keys of the search properties to update.


Only the current lobby owner can update the lobby properties.

Search properties are visible to non-members of the lobby as metadata which can be used to filter and sort
lobby search results.

Only the properties specified in this list of keys will be updated. If the key doesn't exist yet, the property will be
created. If the new property value is nullptr, the property will be deleted. Any existing properties omitted from
this list will be left unmodified.

Search properties must be of the form string_keyN or number_keyN where "N" is a number between 1 and
PFLobbyMaxSearchPropertyCount . e.g. string_key1, number_key14, etc.

searchPropertyValues const char* const*


array of size searchPropertyCount

The values of the search properties to update.


Only the current lobby owner can update the search properties.

Search properties are visible to non-members of the lobby as metadata which can be used to filter and sort
lobby search results.

To delete a value, provide nullptr as its new value.


lobbyPropertyCount uint32_t
The number of lobby properties to update.
Only the current lobby owner can update the lobby properties.

There may only be PFLobbyMaxLobbyPropertyCount concurrent lobby properties at any given time. Therefore, at
most, twice that many unique properties can be specified in this update if half of those properties are being
deleted.

If the property limits are violated, the entire update operation will fail.
lobbyPropertyKeys const char* const*
array of size lobbyPropertyCount
The keys of the lobby properties to update.
Only the current lobby owner can update the lobby properties.

Lobby properties are only visible to members of the lobby.

Only the properties specified in this list of keys will be updated. If the key doesn't exist yet, the property will be
created. If the new property value is nullptr, the property will be deleted. Any existing properties omitted from
this list will be left unmodified.
lobbyPropertyValues const char* const*
array of size lobbyPropertyCount

The values of the lobby properties to update.


Only the current lobby owner can update the lobby properties.

Lobby properties are only visible to members of the lobby.

To delete a value, provide nullptr as its new value.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyJoinConfiguration
5/24/2022 • 2 minutes to read • Edit Online

The initial configuration data used when joining a lobby.

Syntax
struct PFLobbyJoinConfiguration {
uint32_t memberPropertyCount;
const char* const* memberPropertyKeys;
const char* const* memberPropertyValues;
}

Members
memberPropertyCount uint32_t
The number of initial member properties for the joiner of the lobby.
memberPropertyKeys const char* const*
array of size memberPropertyCount

The keys of the initial member properties for the joiner of the lobby.
Per-member properties are only visible to members of the lobby.
memberPropertyValues const char* const*
array of size memberPropertyCount

The values of the initial member properties for the joiner of the lobby.
Per-member properties are only visible to members of the lobby.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyMemberDataUpdate
5/24/2022 • 2 minutes to read • Edit Online

A request to make an update to the member-owned portion of the lobby document.

Syntax
struct PFLobbyMemberDataUpdate {
uint32_t memberPropertyCount;
const char* const* memberPropertyKeys;
const char* const* memberPropertyValues;
}

Members
memberPropertyCount uint32_t
The number of member properties to update for the updating member.
There may only be PFLobbyMaxMemberPropertyCount concurrent properties at any given time per-member.
Therefore, at most, twice that many unique properties can be specified in this update if half of those properties
are being deleted.

If the property limits are violated, the entire update operation will fail.
memberPropertyKeys const char* const*
array of size memberPropertyCount

The keys of the member properties to update for the updating member.
Per-member properties are only visible to members of the lobby.

Only the properties specified in this list of keys will be updated. If the key doesn't exist yet, the property will be
created. If the new property value is nullptr, the property will be deleted. Any existing properties omitted from
this list will be left unmodified.
memberPropertyValues const char* const*
array of size memberPropertyCount

The values of the member properties to update for the updating member.
Per-member properties are only visible to members of the lobby.

To delete a value, provide nullptr as its new value.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyMemberUpdateSummary
5/24/2022 • 2 minutes to read • Edit Online

A collection of hints about an update which has been successfully applied to the lobby on behalf of a member.

Syntax
struct PFLobbyMemberUpdateSummary {
PFEntityKey member;
bool connectionStatusUpdated;
uint32_t updatedMemberPropertyCount;
const char* const* updatedMemberPropertyKeys;
}

Members
member PFEntityKey

The member which performed the update


connectionStatusUpdated bool
A flag indicating whether the member's connection status has updated.
updatedMemberPropertyCount uint32_t
The number of member properties which have been updated for member .
updatedMemberPropertyKeys const char* const*
array of size updatedMemberPropertyCount

The keys of the member properties which have been updated for member .

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbySearchConfiguration
5/24/2022 • 2 minutes to read • Edit Online

The configuration structure used to specify how a PFMultiplayerFindLobbies operation should be performed.

Syntax
struct PFLobbySearchConfiguration {
const PFLobbySearchFriendsFilter* friendsFilter;
const char* filterString;
const char* sortString;
const uint32_t* clientSearchResultCount;
}

Members
friendsFilter const PFLobbySearchFriendsFilter*
may be nullptr
A filter that, when provided, will constrain the lobby search operation to only those owned by the members of
that player's various friend lists.
If omitted, the search operation will search all available lobbies.
filterString const char*
is null-terminated
The query string used to filter which lobbies are returned in the search results.
This string is formatted in an OData-like filtering syntax.

Only the following operators are supported: "and" (logical and), "eq" (equal), "ne" (not equals), "ge" (greater than
or equal), "gt" (greater than), "le" (less than or equal), and "lt" (less than).

The left-hand side of each OData logical expression should be either a search property key (e.g. string_key1,
number_key3, etc) or one of the pre-defined search keys ( PFLobbyMemberCountSearchKey or
PFLobbyAmMemberSearchKey ).

The left-hand side of each OData logical expression should be a search property key.

This string cannot exceed 500 characters.

Example: "string_key1 eq 'CaptureTheFlag' and number_key10 gt 50 and memberCount lt 5"


sortString const char*
is null-terminated
The query string used to sort the lobbies returned in the search results.
This string is formatted in an OData-like order-by syntax: a comma-separated list of search property keys with
an optional specifier to sort in either ascending or descending order.

To specify ascending order, use the "asc" operator after the associated search property key. To specify
descending order, use the "desc" operator after the associated search property key.

Additionally, a special sorting moniker, distance, is supported to enable sorting by closest distance from some
numeric value. For example, "distance{number_key10=5} asc" will sort the results so that lobbies who have their
"number_key10" search property closer to the value "5" will return earlier in the search results.

This string cannot exceed 100 characters.

Example: "string_key1 asc,memberCount desc"


clientSearchResultCount const uint32_t*
may be nullptr
An optional value which, when specified, will limit the number of results provided in the completion response.
This value may only be specified when PFMultiplayerFindLobbies is called with a client-entity.

This value can be no higher than PFLobbyClientRequestedSearchResultCountUpperLimit .

When not specified, the limit on the number of search results is service-defined but will be no greater than
PFLobbyClientRequestedSearchResultCountUpperLimit .

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbySearchFriendsFilter
5/24/2022 • 2 minutes to read • Edit Online

The filter structure used to limit lobby search results to only those lobbies owned by the player's friends.

Syntax
struct PFLobbySearchFriendsFilter {
bool includeSteamFriends;
bool includeFacebookFriends;
const char* includeXboxFriendsToken;
}

Members
includeSteamFriends bool
A flag which includes the player's Steam friends list if their PlayFab account is linked to their Steam account.
includeFacebookFriends bool
A flag which includes the player's Facebook friends list if their PlayFab account is linked to their Facebook
account.
includeXboxFriendsToken const char*
is null-terminated
An Xbox Live token that, when provided, includes the player's Xbox Live friends list if their PlayFab account is
linked to their Xbox Live account.
To retrieve this token, make a POST request to "https://playfabapi.com" with an empty request body using one
of the GetTokenAndSignature APIs provided by Xbox Live.

GetTokenAndSignature APIs are provided natively as part of the Microsoft Game Core Development Kit (GDK).
On all other platforms, these APIs are provided via the Xbox Authentication Library API (XAL).

Remarks
Regardless of which external friend lists are included when constructing this filter, friends from the PlayFab
friends list will always be included.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbySearchResult
5/24/2022 • 2 minutes to read • Edit Online

An entry in the collection of lobby search results received upon successful completion of a
PFMultiplayerFindLobbies operation.

Syntax
struct PFLobbySearchResult {
const char* lobbyId;
const char* connectionString;
const PFEntityKey* ownerEntity;
uint32_t maxMemberCount;
uint32_t currentMemberCount;
uint32_t searchPropertyCount;
const char* const* searchPropertyKeys;
const char* const* searchPropertyValues;
uint32_t friendCount;
const PFEntityKey* friends;
}

Members
lobbyId const char*
is null-terminated
The ID of the found lobby.
connectionString const char*
is null-terminated
The connection string of the found lobby.
connectionString can be null. In this case, an invite is required to join.
ownerEntity const PFEntityKey*
may be nullptr
The current owner of the lobby.
ownerEntity may be null if the lobby doesn't currently have an owner.
maxMemberCount uint32_t
The maximum number of members that can be present in this lobby.
currentMemberCount uint32_t
The current number of members that are present in this lobby.
searchPropertyCount uint32_t
The number of search properties associated with this lobby.
searchPropertyKeys const char* const*
array of size searchPropertyCount
The keys of the search properties associated with this lobby.
searchPropertyValues const char* const*
array of size searchPropertyCount

The values of the search properties associated with this lobby.


friendCount uint32_t
The number of friends in the found lobby, if the lobby search was performed with a PFLobbySearchFriendsFilter .
If the lobby search which generated this search result was not performed with a PFLobbySearchFriendsFilter ,
this value will always be 0.

In some multiplayer social networks, friendship is a unidirectional relationship. One user may "follow" another
or be their friend, but the same is not necessarily true in the reverse direction. Friends will only be returned in
this search result when a bidirectional friendship exists. That is, the user querying for the lobby and the user in
the lobby must both be friends with each other.
friends const PFEntityKey*
array of size friendCount
The list of friends in the found lobby, if the lobby search was performed with a PFLobbySearchFriendsFilter .
If the lobby search which generated this search result was not performed with a PFLobbySearchFriendsFilter ,
this list will always be empty.

In some multiplayer social networks, friendship is a unidirectional relationship. One user may "follow" another
or be their friend, but the same is not necessarily true in the reverse direction. Friends will only be returned in
this search result when a bidirectional friendship exists. That is, the user querying for the lobby and the user in
the lobby must both be friends with each other.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFMatchmakingMatchDetails
5/24/2022 • 2 minutes to read • Edit Online

The resulting match information found by a completed ticket.

Syntax
struct PFMatchmakingMatchDetails {
const char* matchId;
const PFMatchmakingMatchMember* members;
uint32_t memberCount;
const char* const* regionPreferences;
uint32_t regionPreferenceCount;
const char* lobbyArrangementString;
}

Members
matchId const char*
is null-terminated
The ID of the match.
members const PFMatchmakingMatchMember*
The users that have been matched together.
memberCount uint32_t
The count of members that have been matched together.
regionPreferences const char* const*
Preferred regions for the match, sorted from most to least preferred.
regionPreferenceCount uint32_t
The count of preferred regions for the match.
lobbyArrangementString const char*
is null-terminated
The lobby arrangement string associated with the match.
This connection string can optionally be used with PFMultiplayerJoinArrangedLobby() to join a lobby associated
with this match result. The lobby is not created until a user attempts to join it.

Requirements
Header : PFMatchmaking.h

See also
PFMatchmaking members
PFMatchmakingMatchMember
5/24/2022 • 2 minutes to read • Edit Online

A member of a match result.

Syntax
struct PFMatchmakingMatchMember {
PFEntityKey entityKey;
const char* teamId;
const char* attributes;
}

Members
entityKey PFEntityKey
The Entity Key for this match member.
teamId const char*
is null-terminated
The team ID assigned to this match member.
May be empty if the matchmaking queue doesn't use team rules.
attributes const char*
is null-terminated
The attributes for this user in serialized JSON format.

Requirements
Header : PFMatchmaking.h

See also
PFMatchmaking members
PFMatchmakingTicketConfiguration
5/24/2022 • 2 minutes to read • Edit Online

Defines the configuration for a matchmaking ticket.

Syntax
struct PFMatchmakingTicketConfiguration {
uint32_t timeoutInSeconds;
const char* queueName;
uint32_t membersToMatchWithCount;
const PFEntityKey* membersToMatchWith;
}

Members
timeoutInSeconds uint32_t
How long to attempt matchmaking the ticket, in seconds.
queueName const char*
is null-terminated
The ID of a match queue.
membersToMatchWithCount uint32_t
The number of other specific users expected to join the ticket.
membersToMatchWith const PFEntityKey*
array of size membersToMatchWithCount

The PlayFab Entity Keys of other specific users expected to join the ticket.
This field specifies the number of other specific users expected to join the ticket. Typically this list represents a
group of friends or fireteam that are looking for a match together. A match can't be found until all specified
users join the ticket via PFMultiplayerJoinMatchmakingTicketFromId.

Requirements
Header : PFMatchmaking.h

See also
PFMatchmaking members
PFLobbyAddMemberCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the AddMemberCompleted type of state change.

Syntax
struct PFLobbyAddMemberCompletedStateChange : PFLobbyStateChange {
HRESULT result;
PFLobbyHandle lobby;
PFEntityKey localUser;
void* asyncContext;
}

Members
result HRESULT

Indicates the result of the AddMember operation.


The human-readable form of this result can be retrieved via PFMultiplayerGetErrorMessage().
lobby PFLobbyHandle
must not be null
The lobby used in the call associated with this state change.
localUser PFEntityKey
The local user provided to the call associated with this state change.
asyncContext void*
The async context provided to the call associated with this state change.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyCreateAndJoinLobbyCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the CreateAndJoinLobbyCompleted type of state change.

Syntax
struct PFLobbyCreateAndJoinLobbyCompletedStateChange : PFLobbyStateChange {
HRESULT result;
void* asyncContext;
PFLobbyHandle lobby;
}

Members
result HRESULT

Indicates the result of the CreateAndJoinLobby operation.


The human-readable form of this result can be retrieved via PFMultiplayerGetErrorMessage().
asyncContext void*
The async context provided to the call associated with this state change.
lobby PFLobbyHandle
must not be null
The lobby that was created and joined.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyDisconnectedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the Disconnected type of state change.

Syntax
struct PFLobbyDisconnectedStateChange : PFLobbyStateChange {
PFLobbyHandle lobby;
}

Members
lobby PFLobbyHandle
must not be null
The lobby that has disconnected.

Remarks
This state change signals that the lobby has completed disconnecting. This is the last state change that will be
provided for this lobby object. Once this state change is returned to
PFMultiplayerFinishProcessingLobbyStateChanges(), the Lobby object memory will become invalid.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyDisconnectingStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the Disconnecting type of state change.

Syntax
struct PFLobbyDisconnectingStateChange : PFLobbyStateChange {
PFLobbyHandle lobby;
PFLobbyDisconnectingReason reason;
}

Members
lobby PFLobbyHandle
must not be null
The lobby that has started disconnecting.
reason PFLobbyDisconnectingReason
The reason the lobby started disconnecting.

Remarks
This state change signals that the lobby is in the process of disconnecting because there are no local members
actively connected or attempting to reconnect to the lobby. At the point when this state change is provided by
PFMultiplayerStartProcessingLobbyStateChanges(), some operations which require a connected lobby object
will begin to fail such as PFLobbyAddMember.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyFindLobbiesCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the FindLobbiesCompleted type of state change.

Syntax
struct PFLobbyFindLobbiesCompletedStateChange : PFLobbyStateChange {
HRESULT result;
PFEntityKey searchingEntity;
void* asyncContext;
uint32_t searchResultCount;
const PFLobbySearchResult* searchResults;
}

Members
result HRESULT

Indicates the result of the search lobbies operation.


The human-readable form of this result can be retrieved via PFMultiplayerGetErrorMessage().
searchingEntity PFEntityKey
The entity provided to the call associated with this state change.
asyncContext void*
The async context provided to the call associated with this state change.
searchResultCount uint32_t
The number of results returned by the search operation.
searchResults const PFLobbySearchResult*
array of size searchResultCount

The results returned by the search operation.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyForceRemoveMemberCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the ForceRemoveMemberCompleted type of state change.

Syntax
struct PFLobbyForceRemoveMemberCompletedStateChange : PFLobbyStateChange {
HRESULT result;
PFLobbyHandle lobby;
PFEntityKey targetMember;
void* asyncContext;
}

Members
result HRESULT

Indicates the result of the ForceRemoveMember operation.


The human-readable form of this result can be retrieved via PFMultiplayerGetErrorMessage().
lobby PFLobbyHandle
must not be null
The lobby provided to the call associated with this state change.
targetMember PFEntityKey
The member entity provided to the call associated with this state change.
asyncContext void*
The async context provided to the call associated with this state change.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyInviteListenerStatusChangedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the InviteListenerStatusChanged type of state change.

Syntax
struct PFLobbyInviteListenerStatusChangedStateChange : PFLobbyStateChange {
PFEntityKey listeningEntity;
}

Members
listeningEntity PFEntityKey
The entity associated with the invite listener.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyInviteReceivedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the InviteReceived type of state change.

Syntax
struct PFLobbyInviteReceivedStateChange : PFLobbyStateChange {
PFEntityKey listeningEntity;
PFEntityKey invitingEntity;
const char* connectionString;
}

Members
listeningEntity PFEntityKey
The entity which is listening for invites and which has been invited.
invitingEntity PFEntityKey
The entity which has invited the listeningEntity to a lobby.
connectionString const char*
is null-terminated
The connection string of the lobby to which the listeningEntity has been invited.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyJoinArrangedLobbyCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the JoinArrangedLobbyCompleted type of state change.

Syntax
struct PFLobbyJoinArrangedLobbyCompletedStateChange : PFLobbyStateChange {
HRESULT result;
PFEntityKey newMember;
void* asyncContext;
PFLobbyHandle lobby;
}

Members
result HRESULT

Indicates the result of the JoinArrangedLobby operation.


The human-readable form of this result can be retrieved via PFMultiplayerGetErrorMessage().
newMember PFEntityKey
The local member entity provided to the call associated with this state change which is joining this lobby.
asyncContext void*
The async context provided to the call associated with this state change.
lobby PFLobbyHandle
must not be null
The lobby that was created and joined.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyJoinLobbyCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the JoinLobbyCompleted type of state change.

Syntax
struct PFLobbyJoinLobbyCompletedStateChange : PFLobbyStateChange {
HRESULT result;
PFEntityKey newMember;
void* asyncContext;
PFLobbyHandle lobby;
}

Members
result HRESULT

Indicates the result of the JoinLobby operation.


The human-readable form of this result can be retrieved via PFMultiplayerGetErrorMessage().
newMember PFEntityKey
The entity provided to the call associated with this state change which is joining the lobby.
asyncContext void*
The async context provided to the call associated with this state change.
lobby PFLobbyHandle
must not be null
The lobby that was joined.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyLeaveLobbyCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the LeaveLobbyCompleted type of state change.

Syntax
struct PFLobbyLeaveLobbyCompletedStateChange : PFLobbyStateChange {
PFLobbyHandle lobby;
const PFEntityKey* localUser;
void* asyncContext;
}

Members
lobby PFLobbyHandle
must not be null
The lobby provided to the call associated with this state change.
localUser const PFEntityKey*
may be nullptr
The local user provided to the call associated with this state change. May be null.
If this value is null it signifies that the title requested all local members leave the specified lobby.
asyncContext void*
The async context provided to the call associated with this state change.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyMemberAddedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the MemberAdded type of state change.

Syntax
struct PFLobbyMemberAddedStateChange : PFLobbyStateChange {
PFLobbyHandle lobby;
PFEntityKey member;
}

Members
lobby PFLobbyHandle
must not be null
The lobby the new member was added to.
member PFEntityKey
The PlayFab entity which is now a member of the lobby.

Remarks
This state change will be generated by all operations which add members to lobbies such as
PFMultiplayerCreateAndJoinLobby, PFMultiplayerJoinLobby, and PFLobbyAddMember.

When this state change is provided by PFMultiplayerStartProcessingLobbyStateChanges the lobby will update to
reflect the new member in the member list and the member's initial properties will become queryable.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyMemberRemovedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the MemberRemoved type of state change.

Syntax
struct PFLobbyMemberRemovedStateChange : PFLobbyStateChange {
PFLobbyHandle lobby;
PFEntityKey member;
PFLobbyMemberRemovedReason reason;
}

Members
lobby PFLobbyHandle
must not be null
The lobby the new member was removed from.
member PFEntityKey
The member entity which has been removed from the lobby.
reason PFLobbyMemberRemovedReason
The reason member was removed from the lobby.

Remarks
This state change will be generated by all operations which remove members from lobbies such as
PFLobbyLeave() and PFLobbyForceRemoveMember().

When this state change is provided by PFMultiplayerStartProcessingLobbyStateChanges the lobby will update to
remove this member from the member list and the member's properties will be emptied.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyPostUpdateCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the PostUpdateCompleted type of state change.

Syntax
struct PFLobbyPostUpdateCompletedStateChange : PFLobbyStateChange {
HRESULT result;
PFLobbyHandle lobby;
PFEntityKey localUser;
void* asyncContext;
}

Members
result HRESULT

Indicates the result of the update operation.


The human-readable form of this result can be retrieved via PFMultiplayerGetErrorMessage().
lobby PFLobbyHandle
must not be null
The lobby provided to the call associated with this state change.
localUser PFEntityKey
The local user provided to the call associated with this state change.
asyncContext void*
The async context provided to the call associated with this state change.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbySendInviteCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the SendInviteCompleted type of state change.

Syntax
struct PFLobbySendInviteCompletedStateChange : PFLobbyStateChange {
HRESULT result;
PFLobbyHandle lobby;
PFEntityKey sender;
PFEntityKey invitee;
void* asyncContext;
}

Members
result HRESULT

Indicates the result of the SendInvite operation.


The human-readable form of this result can be retrieved via PFMultiplayerGetErrorMessage().
lobby PFLobbyHandle
must not be null
The lobby that the invite was sent for.
sender PFEntityKey
The local user which attempted to send the invite.
invitee PFEntityKey
The entity which was invited.
asyncContext void*
The async context provided to the call associated with this state change.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFLobbyStateChange
5/24/2022 • 2 minutes to read • Edit Online

A generic, base structure representation of an event or change in state.

Syntax
struct PFLobbyStateChange {
PFLobbyStateChangeType stateChangeType;
}

Members
stateChangeType PFLobbyStateChangeType
The specific type of the state change represented.
Use this field to determine which corresponding derived structure is represented by this PFLobbyStateChange
structure header.

Remarks
PFLobbyStateChange structures are reported by PFMultiplayerStartProcessingLobbyStateChanges() for the title
to handle and then promptly pass back via the PFMultiplayerFinishProcessingLobbyStateChanges() method.

The stateChangeType field indicates which kind of state change occurred, and this base structure should then be
cast to a more specific derived structure to retrieve additional event-specific information.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFMultiplayerStartProcessingLobbyStateChanges
PFMultiplayerFinishProcessingLobbyStateChanges
PFLobbyUpdatedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the Updated type of state change.

Syntax
struct PFLobbyUpdatedStateChange : PFLobbyStateChange {
PFLobbyHandle lobby;
bool ownerUpdated;
bool maxMembersUpdated;
bool accessPolicyUpdated;
bool membershipLockUpdated;
uint32_t updatedSearchPropertyCount;
const char* const* updatedSearchPropertyKeys;
uint32_t updatedLobbyPropertyCount;
const char* const* updatedLobbyPropertyKeys;
uint32_t memberUpdateCount;
const PFLobbyMemberUpdateSummary* memberUpdates;
}

Members
lobby PFLobbyHandle
must not be null
The lobby which was updated.
ownerUpdated bool
A flag indicating if the lobby's owner was updated.
maxMembersUpdated bool
A flag indicating if the maxmimum number of members allowed in the lobby has been updated.
accessPolicyUpdated bool
A flag indicating if the lobby's access policy was updated.
membershipLockUpdated bool
A flag indicating if the lobby's membership lock has updated.
updatedSearchPropertyCount uint32_t
The number of search properties which have been updated.
updatedSearchPropertyKeys const char* const*
array of size updatedSearchPropertyCount

The keys of the search properties which have been updated.


updatedLobbyPropertyCount uint32_t
The number of lobby properties which have been updated.
updatedLobbyPropertyKeys const char* const*
array of size updatedLobbyPropertyCount

The keys of the lobby properties which have been updated.


memberUpdateCount uint32_t
The number of updates to the lobby members.
memberUpdates const PFLobbyMemberUpdateSummary*
array of size memberUpdateCount

The set of member updates.

Remarks
This state change signifies that the lobby has updated and provides hints as to which values have changed.
Multiple updates may be provided by a single call to PFMultiplayerStartProcessingLobbyStateChanges(). All
state reflected by these updates will become available simultaneously when
PFMultiplayerStartProcessingLobbyStateChanges() is called, so the updates can be reconciled either individually
or as a batch.

Requirements
Header : PFLobby.h

See also
PFLobby members
PFMatchmakingStateChange
5/24/2022 • 2 minutes to read • Edit Online

A generic, base structure representation of an event or change in state.

Syntax
struct PFMatchmakingStateChange {
PFMatchmakingStateChangeType stateChangeType;
}

Members
stateChangeType PFMatchmakingStateChangeType
The specific type of the state change represented.
Use this field to determine which corresponding derived structure is represented by this
PFMatchmakingStateChange structure header.

Remarks
PFMatchmakingStateChange structures are reported by
PFMultiplayerStartProcessingMatchmakingStateChanges() for the title to handle and then promptly pass back
via the PFMultiplayerFinishProcessingMatchmakingStateChanges() method.

The stateChangeType field indicates which kind of state change occurred, and this base structure should then be
cast to a more specific derived structure to retrieve additional event-specific information.

Requirements
Header : PFMatchmaking.h

See also
PFMatchmaking members
PFMultiplayerStartProcessingMatchmakingStateChanges
PFMultiplayerFinishProcessingMatchmakingStateChanges
PFMatchmakingTicketCompletedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the TicketCompleted type of state change.

Syntax
struct PFMatchmakingTicketCompletedStateChange : PFMatchmakingStateChange {
HRESULT result;
PFMatchmakingTicketHandle ticket;
void* asyncContext;
}

Members
result HRESULT

An error code indicating whether the ticket succeeded or, if it failed, why it failed.
ticket PFMatchmakingTicketHandle
must not be null
The matchmaking ticket that completed.
asyncContext void*
The async context provided to the call associated with this state change.

Requirements
Header : PFMatchmaking.h

See also
PFMatchmaking members
PFMatchmakingTicketStatusChangedStateChange
5/24/2022 • 2 minutes to read • Edit Online

Information specific to the TicketStatusChanged type of state change.

Syntax
struct PFMatchmakingTicketStatusChangedStateChange : PFMatchmakingStateChange {
PFMatchmakingTicketHandle ticket;
}

Members
ticket PFMatchmakingTicketHandle
must not be null
The matchmaking ticket whose status changed.
The new ticket status can be retrieved via PFMatchmakingTicketGetStatus.

Requirements
Header : PFMatchmaking.h

See also
PFMatchmaking members
PFMultiplayerAllocateMemoryCallback
5/24/2022 • 2 minutes to read • Edit Online

A callback invoked every time a new memory buffer must be dynamically allocated by the PlayFab Multiplayer
library.

Syntax
typedef
void* (*PFMultiplayerAllocateMemoryCallback)(
size_t size,
uint32_t memoryTypeId
)

Parameters
size size_t

The size of the allocation to be made. This value will never be zero.
memoryTypeId uint32_t
An opaque identifier representing the PlayFab Multiplayer library internal category of memory being allocated.
This value should be ignored.
Return value
Type: void*
A pointer to an allocated block of memory of the specified size, or nullptr if the allocation failed.

Remarks
This callback is optionally installed using the PFMultiplayerSetMemoryCallbacks() method.

The callback must allocate and return a pointer to a contiguous block of memory of the specified size that will
remain valid until the title's corresponding PFMultiplayerFreeMemoryCallback is invoked to release it. If this is
not possible, the callback must return nullptr to fail the allocation. Memory allocation failures are sometimes
considered benign but will usually cause current PlayFab Multiplayer library operation(s) to fail.

Every non-nullptr returned by this method will be subsequently passed to the corresponding
PFMultiplayerFreeMemoryCallback once the memory is no longer needed.

Requirements
Header : PFMultiplayer.h

See also
PFMultiplayer members
PFMultiplayerFreeMemoryCallback
PFMultiplayerSetMemoryCallbacks
PFMultiplayerFreeMemoryCallback
5/24/2022 • 2 minutes to read • Edit Online

A callback invoked every time a previously allocated memory buffer is no longer needed by the PlayFab
Multiplayer library and can be freed.

Syntax
typedef
void (*PFMultiplayerFreeMemoryCallback)(
void* pointer,
uint32_t memoryTypeId
)

Parameters
pointer void*
Post_invalid
A pointer to a memory buffer previously allocated. This value will never be nullptr.
memoryTypeId uint32_t
An opaque identifier representing the PlayFab Multiplayer library internal category of memory being freed. This
value should be ignored.
Return value
Type: void
The callback does not return a value.

Remarks
This callback is optionally installed using the PFMultiplayerSetMemoryCallbacks() method.

The callback is invoked whenever the PlayFab Multiplayer library has finished using a memory buffer previously
returned by the title's corresponding PFMultiplayerAllocateMemoryCallback, so that the title can free the
memory buffer.

Requirements
Header : PFMultiplayer.h

See also
PFMultiplayer members
PFMultiplayerAllocateMemoryCallback
PFMultiplayerSetMemoryCallbacks
PFEntityKey
5/24/2022 • 2 minutes to read • Edit Online

PFEntityKey data model. Combined entity type and ID structure which uniquely identifies a single entity.

Syntax
typedef struct PFEntityKey {
const char* id;
const char* type;
} PFEntityKey;

Members
id const char*
Null_terminated
Unique ID of the entity.
type const char*
Null_terminated
Entity type. See https://docs.microsoft.com/gaming/playfab/features/data/entities/available-built-in-entity-
types.
Player entities are typically the title_player_account type. For more information, see See
https://docs.microsoft.com/gaming/playfab/features/data/entities/available-built-in-entity-types.

Remarks
For more information about entities, see https://docs.microsoft.com/gaming/playfab/features/data/entities/.

Requirements
Header : PFEntityKey.h
PlayFab Multiplayer Unity SDK
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

Classes
NAME DESC RIP T IO N

Lobby

LobbyArrangedJoinConfiguration The initial configuration data used when joining an arranged


lobby.

LobbyCreateConfiguration The initial configuration data used when creating a lobby.

LobbyDataUpdate A request to make an update to the shared portion of the


lobby on behalf of a member.

LobbyError

LobbyJoinConfiguration The initial configuration data for the member creating and
joining the lobby.

LobbyMemberUpdateSummary A collection of hints about an update which has been


successfully applied to the lobby on behalf of a member.

LobbySearchConfiguration The configuration structure used to specify how a


!:FindLobbies operation should be performed.

LobbySearchFriendsFilter The filter structure used to limit lobby search results to only
those lobbies owned by the player's friends.

LobbySearchResult An entry in the collection of lobby search results received


upon successful completion of a FindLobbies operation.

MatchmakingMatchDetails

MatchmakingTicket

MatchmakingTicketMatchMember

PFEntityKey PFEntityKey data model. Combined entity type and ID


structure which uniquely identifies a single entity.

PlayFabMultiplayer
NAME DESC RIP T IO N

PlayFabMultiplayerErrorArgs An event argument class representing a PFMultiplayer error.

PlayfabMultiplayerEventProcessor

Structs
NAME DESC RIP T IO N

MatchUser

Enums
NAME DESC RIP T IO N

LobbyAccessPolicy The access policy for the lobby

LobbyDisconnectingReason Reasons the client no longer has access to the Lobby.

LobbyInviteListenerStatus Values representing the current status of an invite listener.

LobbyMemberRemovedReason Reasons why a member was removed from a lobby.

LobbyMembershipLock

LobbyOwnerMigrationPolicy The available policies the lobby service can use to migrate
lobby ownership between members.

LogLevelType The amount of logging that is enabled.

MatchmakingTicketStatus The possible states for a matchmaking ticket.


Class Lobby
5/24/2022 • 2 minutes to read • Edit Online

public class Lobby

Properties
NAME DESC RIP T IO N

AccessPolicy

ConnectionString

Id

MaxMemberCount

MembershipLock

OwnerMigrationPolicy

Methods
NAME DESC RIP T IO N

AddMember Add a local user as a member to the lobby.

ForceRemoveMember Forcibly remove an entity from the lobby.

GetLobbyProperties

GetMemberProperties

GetMembers

GetSearchProperties

Leave (2 methods)

LeaveAllLocalUsers

PostUpdate (6 methods)

SendInvite Send an invite to this lobby from the local user to the invited
entity. (2 methods)

TryGetOwner
See Also
namespace PlayFab.Multiplayer
Lobby.AccessPolicy property
5/24/2022 • 2 minutes to read • Edit Online

public LobbyAccessPolicy AccessPolicy { get; }

See Also
enum LobbyAccessPolicy
class Lobby
namespace PlayFab.Multiplayer
Lobby.ConnectionString property
5/24/2022 • 2 minutes to read • Edit Online

public string ConnectionString { get; }

See Also
class Lobby
namespace PlayFab.Multiplayer
Lobby.Id property
5/24/2022 • 2 minutes to read • Edit Online

public string Id { get; }

See Also
class Lobby
namespace PlayFab.Multiplayer
Lobby.MaxMemberCount property
5/24/2022 • 2 minutes to read • Edit Online

public uint MaxMemberCount { get; }

See Also
class Lobby
namespace PlayFab.Multiplayer
Lobby.MembershipLock property
5/24/2022 • 2 minutes to read • Edit Online

public LobbyMembershipLock MembershipLock { get; }

See Also
enum LobbyMembershipLock
class Lobby
namespace PlayFab.Multiplayer
Lobby.OwnerMigrationPolicy property
5/24/2022 • 2 minutes to read • Edit Online

public LobbyOwnerMigrationPolicy OwnerMigrationPolicy { get; }

See Also
enum LobbyOwnerMigrationPolicy
class Lobby
namespace PlayFab.Multiplayer
Lobby.AddMember method
5/24/2022 • 2 minutes to read • Edit Online

Add a local user as a member to the lobby.

public void AddMember(PFEntityKey localUser, IDictionary<string, string> memberProperties)

PA RA M ET ER DESC RIP T IO N

localUser The PlayFab Entity Key of the local user to add to the lobby
as a member.

memberProperties The initial member properties to set for this user when they
join the lobby.

Remarks
This is an asynchronous operation. Upon successful completion, the title will be provided a OnLobbyMemberAdded
event followed by a OnAddMemberCompleted event with the result field set to Succeeded (0). Upon a failed
completion, the result field will be set to Failed (negative value).
This method is used to add an additional local PlayFab entity to a pre-existing lobby object. Because the lobby
object, must have already been created either via a call to CreateAndJoinLobby or JoinLobby , this method is
primarily useful for multiple local user scenarios.
This is an asynchronous operation. The member added via this method will not be reflected in the lists returned
by GetMembers until the asynchronous operation successfully completes.

See Also
class PFEntityKey
class Lobby
namespace PlayFab.Multiplayer
Lobby.ForceRemoveMember method
5/24/2022 • 2 minutes to read • Edit Online

Forcibly remove an entity from the lobby.

public void ForceRemoveMember(PFEntityKey targetMember, bool preventRejoin)

PA RA M ET ER DESC RIP T IO N

targetMember The member to forcibly remove.

preventRejoin A flag indicating whether targetMember will be prevented


from rejoining the lobby after being removed.

Remarks
This is an asynchronous operation. Upon successful completion, the title will be provided a
OnLobbyMemberRemoved event followed by a OnForceRemoveMemberCompleted event with the result field set to
LobbyStateChangeResult.Succeeded . Upon a failed completion, the title will be provided a
OnForceRemoveMemberCompleted event with the result field set to a failure

One of the local PlayFab entities present in this lobby must be the owner for this operation to succeed. If the
local owning entity who initiated this operation loses their ownership status while the operation is in progress,
the operation will fail asynchronously and the provided OnForceRemoveMemberCompleted event result which will be
set to !:LobbyStateChangeResult.UserNotAuthorized
This is an asynchronous operation. The member removed via this method will not be removed from the lists
returned by GetMembers until the asynchronous operation successfully completes and a OnLobbyMemberRemoved
event

See Also
class PFEntityKey
class Lobby
namespace PlayFab.Multiplayer
Lobby.GetLobbyProperties method
5/24/2022 • 2 minutes to read • Edit Online

public IDictionary<string, string> GetLobbyProperties()

See Also
class Lobby
namespace PlayFab.Multiplayer
Lobby.GetMemberProperties method
5/24/2022 • 2 minutes to read • Edit Online

public IDictionary<string, string> GetMemberProperties(PFEntityKey member)

See Also
class PFEntityKey
class Lobby
namespace PlayFab.Multiplayer
Lobby.GetMembers method
5/24/2022 • 2 minutes to read • Edit Online

public IList<PFEntityKey> GetMembers()

See Also
class PFEntityKey
class Lobby
namespace PlayFab.Multiplayer
Lobby.GetSearchProperties method
5/24/2022 • 2 minutes to read • Edit Online

public IDictionary<string, string> GetSearchProperties()

See Also
class Lobby
namespace PlayFab.Multiplayer
Lobby.Leave method
5/24/2022 • 2 minutes to read • Edit Online

Lobby.Leave (1 of 2)
public void Leave(PFEntityKey localUser)

See Also 1
class PFEntityKey
class Lobby
namespace PlayFab.Multiplayer

Lobby.Leave (2 of 2)
public void Leave(PlayFabAuthenticationContext localUser)

See Also 2
class Lobby
namespace PlayFab.Multiplayer
Lobby.LeaveAllLocalUsers method
5/24/2022 • 2 minutes to read • Edit Online

public void LeaveAllLocalUsers()

See Also
class Lobby
namespace PlayFab.Multiplayer
Lobby.PostUpdate method
5/24/2022 • 2 minutes to read • Edit Online

Lobby.PostUpdate (1 of 6)
public void PostUpdate(PFEntityKey localUser, IDictionary<string, string> memberProperties)

See Also 1
class PFEntityKey
class Lobby
namespace PlayFab.Multiplayer

Lobby.PostUpdate (2 of 6)
public void PostUpdate(PFEntityKey localUser, LobbyDataUpdate lobbyUpdate)

See Also 2
class PFEntityKey
class LobbyDataUpdate
class Lobby
namespace PlayFab.Multiplayer

Lobby.PostUpdate (3 of 6)
public void PostUpdate(PlayFabAuthenticationContext localUser,
IDictionary<string, string> memberProperties)

See Also 3
class Lobby
namespace PlayFab.Multiplayer

Lobby.PostUpdate (4 of 6)
public void PostUpdate(PlayFabAuthenticationContext localUser, LobbyDataUpdate lobbyUpdate)

See Also 4
class LobbyDataUpdate
class Lobby
namespace PlayFab.Multiplayer

Lobby.PostUpdate (5 of 6)
public void PostUpdate(PFEntityKey localUser, LobbyDataUpdate lobbyUpdate,
IDictionary<string, string> memberProperties)

See Also 5
class PFEntityKey
class LobbyDataUpdate
class Lobby
namespace PlayFab.Multiplayer

Lobby.PostUpdate (6 of 6)
public void PostUpdate(PlayFabAuthenticationContext localUser, LobbyDataUpdate lobbyUpdate,
IDictionary<string, string> memberProperties)

See Also 6
class LobbyDataUpdate
class Lobby
namespace PlayFab.Multiplayer
Lobby.SendInvite method
5/24/2022 • 2 minutes to read • Edit Online

Lobby.SendInvite (1 of 2)
Send an invite to this lobby from the local user to the invited entity.

public void SendInvite(PFEntityKey sender, PFEntityKey invitee)

PA RA M ET ER DESC RIP T IO N

sender The local user sending the invite.

invitee The invited entity.

Remarks 1
This is an asynchronous operation. Upon successful completion, the title will be provided a
OnLobbySendInviteCompleted with the !:PlayFabMultiplayer.OnLobbySendInviteCompleted.result field set to
LobbyStateChangeResult.Succeeded . Upon a failed completion, the title will be provided a
OnLobbySendInviteCompleted with the !:PlayFabMultiplayer.OnLobbySendInviteCompleted.result field set to a
failure !:LobbyStateChangeResult.
The sender must be a local user of this lobby which joined from this client.

See Also 1
class PFEntityKey
class Lobby
namespace PlayFab.Multiplayer

Lobby.SendInvite (2 of 2)
Send an invite to this lobby from the local user to the invited entity.

public void SendInvite(PlayFabAuthenticationContext sender, PFEntityKey invitee)

PA RA M ET ER DESC RIP T IO N

sender The local user sending the invite.

invitee The invited entity.

Remarks 2
This is an asynchronous operation. Upon successful completion, the title will be provided a
OnLobbySendInviteCompleted with the !:PlayFabMultiplayer.OnLobbySendInviteCompleted.result field set to
LobbyStateChangeResult.Succeeded . Upon a failed completion, the title will be provided a
OnLobbySendInviteCompleted with the !:PlayFabMultiplayer.OnLobbySendInviteCompleted.result field set to a
failure !:LobbyStateChangeResult.
The sender must be a local user of this lobby which joined from this client.

See Also 2
class PFEntityKey
class Lobby
namespace PlayFab.Multiplayer
Lobby.TryGetOwner method
5/24/2022 • 2 minutes to read • Edit Online

public bool TryGetOwner(out PFEntityKey owner)

See Also
class PFEntityKey
class Lobby
namespace PlayFab.Multiplayer
Class LobbyArrangedJoinConfiguration
5/24/2022 • 2 minutes to read • Edit Online

The initial configuration data used when joining an arranged lobby.

public class LobbyArrangedJoinConfiguration

Constructors
NAME DESC RIP T IO N

LobbyArrangedJoinConfiguration The default constructor.

Properties
NAME DESC RIP T IO N

AccessPolicy The access policy for the lobby, if the joiner is the first
member in the lobby.

MaxMemberCount The maximum number of members allowed in the lobby, if


joiner is the first member in the lobby.

MemberProperties The initial member properties for the joiner of the lobby.

OwnerMigrationPolicy The owner migration policy for the lobby, if the joiner is the
first member in the lobby.

See Also
namespace PlayFab.Multiplayer
LobbyArrangedJoinConfiguration constructor
5/24/2022 • 2 minutes to read • Edit Online

The default constructor.

public LobbyArrangedJoinConfiguration()

See Also
class LobbyArrangedJoinConfiguration
namespace PlayFab.Multiplayer
LobbyArrangedJoinConfiguration.AccessPolicy
property
5/24/2022 • 2 minutes to read • Edit Online

The access policy for the lobby, if the joiner is the first member in the lobby.

public LobbyAccessPolicy AccessPolicy { get; set; }

See Also
enum LobbyAccessPolicy
class LobbyArrangedJoinConfiguration
namespace PlayFab.Multiplayer
LobbyArrangedJoinConfiguration.MaxMemberCount
property
5/24/2022 • 2 minutes to read • Edit Online

The maximum number of members allowed in the lobby, if joiner is the first member in the lobby.

public uint MaxMemberCount { get; set; }

Remarks
This value must be at least PlayFabMultiplayer.LobbyMaxMemberCountLowerLimit and no more than
PlayFabMultiplayer.LobbyMaxMemberCountUpperLimit .
If a client would violate this limit by calling !:JoinLobby() or !:Lobby.AddMember, the operation will fail
asynchronously and !:LobbyJoinCompletedStateChange.result or
!:LobbyAddMemberCompletedStateChange.result, respectively, will be set to
!:LobbyStateChangeResult.LobbyNotJoinable.

See Also
class LobbyArrangedJoinConfiguration
namespace PlayFab.Multiplayer
LobbyArrangedJoinConfiguration.MemberProperties
property
5/24/2022 • 2 minutes to read • Edit Online

The initial member properties for the joiner of the lobby.

public IDictionary<string, string> MemberProperties { get; set; }

See Also
class LobbyArrangedJoinConfiguration
namespace PlayFab.Multiplayer
LobbyArrangedJoinConfiguration.OwnerMigrationPolicy
property
5/24/2022 • 2 minutes to read • Edit Online

The owner migration policy for the lobby, if the joiner is the first member in the lobby.

public LobbyOwnerMigrationPolicy OwnerMigrationPolicy { get; set; }

Remarks
This value cannot be set to LobbyOwnerMigrationPolicy.Server .

See Also
enum LobbyOwnerMigrationPolicy
class LobbyArrangedJoinConfiguration
namespace PlayFab.Multiplayer
Class LobbyCreateConfiguration
5/24/2022 • 2 minutes to read • Edit Online

The initial configuration data used when creating a lobby.

public class LobbyCreateConfiguration

Constructors
NAME DESC RIP T IO N

LobbyCreateConfiguration The default constructor.

Properties
NAME DESC RIP T IO N

AccessPolicy The access policy for the new lobby.

LobbyProperties The initial lobby properties for the new lobby.

MaxMemberCount The maximum number of members allowed in the new


lobby.

OwnerMigrationPolicy The owner migration policy for the new lobby.

SearchProperties The initial search properties for the new lobby.

See Also
namespace PlayFab.Multiplayer
LobbyCreateConfiguration constructor
5/24/2022 • 2 minutes to read • Edit Online

The default constructor.

public LobbyCreateConfiguration()

See Also
class LobbyCreateConfiguration
namespace PlayFab.Multiplayer
LobbyCreateConfiguration.AccessPolicy property
5/24/2022 • 2 minutes to read • Edit Online

The access policy for the new lobby.

public LobbyAccessPolicy AccessPolicy { get; set; }

See Also
enum LobbyAccessPolicy
class LobbyCreateConfiguration
namespace PlayFab.Multiplayer
LobbyCreateConfiguration.LobbyProperties
property
5/24/2022 • 2 minutes to read • Edit Online

The initial lobby properties for the new lobby.

public IDictionary<string, string> LobbyProperties { get; set; }

See Also
class LobbyCreateConfiguration
namespace PlayFab.Multiplayer
LobbyCreateConfiguration.MaxMemberCount
property
5/24/2022 • 2 minutes to read • Edit Online

The maximum number of members allowed in the new lobby.

public uint MaxMemberCount { get; set; }

Remarks
This value must be at least PlayFabMultiplayer.LobbyMaxMemberCountLowerLimit and no more than
PlayFabMultiplayer.LobbyMaxMemberCountUpperLimit .
If a client would violate this limit by calling !:JoinLobby() or !:Lobby.AddMember, the operation will fail
asynchronously and !:OnLobbyJoinCompleted.result or !:OnLobbyAddMemberCompleted.result, respectively,
will be set to !:LobbyStateChangeResult.LobbyNotJoinable.

See Also
class LobbyCreateConfiguration
namespace PlayFab.Multiplayer
LobbyCreateConfiguration.OwnerMigrationPolicy
property
5/24/2022 • 2 minutes to read • Edit Online

The owner migration policy for the new lobby.

public LobbyOwnerMigrationPolicy OwnerMigrationPolicy { get; set; }

Remarks
This value cannot be set to LobbyOwnerMigrationPolicy.Server .

See Also
enum LobbyOwnerMigrationPolicy
class LobbyCreateConfiguration
namespace PlayFab.Multiplayer
LobbyCreateConfiguration.SearchProperties
property
5/24/2022 • 2 minutes to read • Edit Online

The initial search properties for the new lobby.

public IDictionary<string, string> SearchProperties { get; set; }

See Also
class LobbyCreateConfiguration
namespace PlayFab.Multiplayer
Class LobbyDataUpdate
5/24/2022 • 2 minutes to read • Edit Online

A request to make an update to the shared portion of the lobby on behalf of a member.

public class LobbyDataUpdate

Constructors
NAME DESC RIP T IO N

LobbyDataUpdate The default constructor.

Properties
NAME DESC RIP T IO N

AccessPolicy An optional, updated access policy for this lobby.

LobbyProperties The lobby properties to update.

MaxMemberCount An optional, updated capacity for the number of members in


this lobby.

MembershipLock An optional update to the membership lock on this lobby.

NewOwner An optional, new owner of the lobby.

SearchProperties The search properties to update.

See Also
namespace PlayFab.Multiplayer
LobbyDataUpdate constructor
5/24/2022 • 2 minutes to read • Edit Online

The default constructor.

public LobbyDataUpdate()

See Also
class LobbyDataUpdate
namespace PlayFab.Multiplayer
LobbyDataUpdate.AccessPolicy property
5/24/2022 • 2 minutes to read • Edit Online

An optional, updated access policy for this lobby.

public LobbyAccessPolicy? AccessPolicy { get; set; }

Remarks
This value can only be updated by the current lobby owner.

See Also
enum LobbyAccessPolicy
class LobbyDataUpdate
namespace PlayFab.Multiplayer
LobbyDataUpdate.LobbyProperties property
5/24/2022 • 2 minutes to read • Edit Online

The lobby properties to update.

public IDictionary<string, string> LobbyProperties { get; set; }

Remarks
Only the current lobby owner can update the lobby properties.
There may only be PlayFabMultiplayer.LobbyMaxLobbyPropertyCount concurrent lobby properties at any given
time. Therefore, at most, twice that many unique properties can be specified in this update if half of those
properties are being deleted.
If the property limits are violated, the entire update operation will fail.

See Also
class LobbyDataUpdate
namespace PlayFab.Multiplayer
LobbyDataUpdate.MaxMemberCount property
5/24/2022 • 2 minutes to read • Edit Online

An optional, updated capacity for the number of members in this lobby.

public uint? MaxMemberCount { get; set; }

Remarks
This new value must be greater than than the number of members currently in the lobby and less than
LobbyMaxMemberCountUpperLimit .

This value can only be updated by the current lobby owner.

See Also
class LobbyDataUpdate
namespace PlayFab.Multiplayer
LobbyDataUpdate.MembershipLock property
5/24/2022 • 2 minutes to read • Edit Online

An optional update to the membership lock on this lobby.

public LobbyMembershipLock? MembershipLock { get; set; }

Remarks
This value can only be updated by the current lobby owner.

See Also
enum LobbyMembershipLock
class LobbyDataUpdate
namespace PlayFab.Multiplayer
LobbyDataUpdate.NewOwner property
5/24/2022 • 2 minutes to read • Edit Online

An optional, new owner of the lobby.

public PFEntityKey NewOwner { get; set; }

Remarks
This value can only be updated under one of the following conditions:
* The member updating this field is the lobby's current owner * The owner migration policy is
LobbyOwnerMigrationPolicy.Manual and there is currently no owner * The owner migration policy is
LobbyOwnerMigrationPolicy.None`

See Also
class PFEntityKey
class LobbyDataUpdate
namespace PlayFab.Multiplayer
LobbyDataUpdate.SearchProperties property
5/24/2022 • 2 minutes to read • Edit Online

The search properties to update.

public IDictionary<string, string> SearchProperties { get; set; }

Remarks
Only the current lobby owner can update the search properties.
There may only be PlayFabMultiplayer.LobbyMaxSearchPropertyCount concurrent search properties at any given
time. Therefore, at most, twice that many unique properties can be specified in this update if half of those
properties are being deleted.
If the property limits are violated, the entire update operation will fail.

See Also
class LobbyDataUpdate
namespace PlayFab.Multiplayer
Class LobbyError
5/24/2022 • 2 minutes to read • Edit Online

public class LobbyError

Constructors
NAME DESC RIP T IO N

LobbyError The default constructor.

Constants
NAME DESC RIP T IO N

const InvalidArg

const Success

Methods
NAME DESC RIP T IO N

static FAILED

static SUCCEEDED

See Also
namespace PlayFab.Multiplayer
LobbyError constructor
5/24/2022 • 2 minutes to read • Edit Online

The default constructor.

public LobbyError()

See Also
class LobbyError
namespace PlayFab.Multiplayer
LobbyError.InvalidArg field
5/24/2022 • 2 minutes to read • Edit Online

public const int InvalidArg;

See Also
class LobbyError
namespace PlayFab.Multiplayer
LobbyError.Success field
5/24/2022 • 2 minutes to read • Edit Online

public const int Success;

See Also
class LobbyError
namespace PlayFab.Multiplayer
LobbyError.FAILED method
5/24/2022 • 2 minutes to read • Edit Online

public static bool FAILED(int error)

See Also
class LobbyError
namespace PlayFab.Multiplayer
LobbyError.SUCCEEDED method
5/24/2022 • 2 minutes to read • Edit Online

public static bool SUCCEEDED(int error)

See Also
class LobbyError
namespace PlayFab.Multiplayer
Class LobbyJoinConfiguration
5/24/2022 • 2 minutes to read • Edit Online

The initial configuration data for the member creating and joining the lobby.

public class LobbyJoinConfiguration

Constructors
NAME DESC RIP T IO N

LobbyJoinConfiguration The default constructor.

Properties
NAME DESC RIP T IO N

MemberProperties The member properties for the lobby.

See Also
namespace PlayFab.Multiplayer
LobbyJoinConfiguration constructor
5/24/2022 • 2 minutes to read • Edit Online

The default constructor.

public LobbyJoinConfiguration()

See Also
class LobbyJoinConfiguration
namespace PlayFab.Multiplayer
LobbyJoinConfiguration.MemberProperties
property
5/24/2022 • 2 minutes to read • Edit Online

The member properties for the lobby.

public IDictionary<string, string> MemberProperties { get; set; }

See Also
class LobbyJoinConfiguration
namespace PlayFab.Multiplayer
Class LobbyMemberUpdateSummary
5/24/2022 • 2 minutes to read • Edit Online

A collection of hints about an update which has been successfully applied to the lobby on behalf of a member.

public class LobbyMemberUpdateSummary

Properties
NAME DESC RIP T IO N

ConnectionStatusUpdated A flag indicating whether the member's connection status


has updated.

Member The member which performed the update

UpdatedMemberPropertyKeys The member properties which have been updated for


member .

See Also
namespace PlayFab.Multiplayer
LobbyMemberUpdateSummary.ConnectionStatusUpdated
property
5/24/2022 • 2 minutes to read • Edit Online

A flag indicating whether the member's connection status has updated.

public bool ConnectionStatusUpdated { get; }

See Also
class LobbyMemberUpdateSummary
namespace PlayFab.Multiplayer
LobbyMemberUpdateSummary.Member property
5/24/2022 • 2 minutes to read • Edit Online

The member which performed the update

public PFEntityKey Member { get; }

See Also
class PFEntityKey
class LobbyMemberUpdateSummary
namespace PlayFab.Multiplayer
LobbyMemberUpdateSummary.UpdatedMemberPropertyKeys
property
5/24/2022 • 2 minutes to read • Edit Online

The member properties which have been updated for member .

public List<string> UpdatedMemberPropertyKeys { get; }

See Also
class LobbyMemberUpdateSummary
namespace PlayFab.Multiplayer
Class LobbySearchConfiguration
5/24/2022 • 2 minutes to read • Edit Online

The configuration structure used to specify how a !:FindLobbies operation should be performed.

public class LobbySearchConfiguration

Constructors
NAME DESC RIP T IO N

LobbySearchConfiguration The default constructor.

Properties
NAME DESC RIP T IO N

ClientSearchResultCount An optional value which, when specified, will limit the


number of results provided in the completion response.

FilterString The query string used to filter which lobbies are returned in
the search results.

FriendsFilter A filter that, when provided, will constrain the lobby search
operation to only those owned by the members of that
player's various friend lists.

SortString The query string used to sort the lobbies returned in the
search results.

See Also
namespace PlayFab.Multiplayer
LobbySearchConfiguration constructor
5/24/2022 • 2 minutes to read • Edit Online

The default constructor.

public LobbySearchConfiguration()

See Also
class LobbySearchConfiguration
namespace PlayFab.Multiplayer
LobbySearchConfiguration.ClientSearchResultCount
property
5/24/2022 • 2 minutes to read • Edit Online

An optional value which, when specified, will limit the number of results provided in the completion response.

public uint? ClientSearchResultCount { get; set; }

Remarks
This value may only be specified when !:FindLobbies is called with a client-entity.
This value can be no higher than PlayFabMultiplayer.LobbyClientRequestedSearchResultCountUpperLimit .
When not specified, the limit on the number of search results is service-defined but will be no greater than
PlayFabMultiplayer.LobbyClientRequestedSearchResultCountUpperLimit .

See Also
class LobbySearchConfiguration
namespace PlayFab.Multiplayer
LobbySearchConfiguration.FilterString property
5/24/2022 • 2 minutes to read • Edit Online

The query string used to filter which lobbies are returned in the search results.

public string FilterString { get; set; }

Remarks
This string is formatted in an OData-like filtering syntax.
Only the following operators are supported: "and" (logical and), "eq" (equal), "ne" (not equals), "ge" (greater than
or equal), "gt" (greater than), "le" (less than or equal), and "lt" (less than).
The left-hand side of each OData logical expression should be either a search property key (e.g. string_key1,
number_key3, etc) or one of the pre-defined search keys (!:LobbyMemberCountSearchKey or
!:LobbyMemberSearchKey).
The left-hand side of each OData logical expression should be a search property key.
This string cannot exceed 500 characters.
Example: "string_key1 eq 'CaptureTheFlag' and number_key10 gt 50 and memberCount lt 5"

See Also
class LobbySearchConfiguration
namespace PlayFab.Multiplayer
LobbySearchConfiguration.FriendsFilter property
5/24/2022 • 2 minutes to read • Edit Online

A filter that, when provided, will constrain the lobby search operation to only those owned by the members of
that player's various friend lists.

public LobbySearchFriendsFilter FriendsFilter { get; }

Remarks
If omitted, the search operation will search all available lobbies.

See Also
class LobbySearchFriendsFilter
class LobbySearchConfiguration
LobbySearchConfiguration.SortString property
5/24/2022 • 2 minutes to read • Edit Online

The query string used to sort the lobbies returned in the search results.

public string SortString { get; set; }

Remarks
This string is formatted in an OData-like order-by syntax: a comma-separated list of search property keys with
an optional specifier to sort in either ascending or descending order.
To specify ascending order, use the "asc" operator after the associated search property key. To specify
descending order, use the "desc" operator after the associated search property key.
Additionally, a special sorting moniker, distance, is supported to enable sorting by closest distance from some
numeric value. For example, "distance{number_key10=5} asc" will sort the results so that lobbies who have their
"number_key10" search property closer to the value "5" will return earlier in the search results.
This string cannot exceed 100 characters.
Example: "string_key1 asc,memberCount desc"

See Also
class LobbySearchConfiguration
namespace PlayFab.Multiplayer
Class LobbySearchFriendsFilter
5/24/2022 • 2 minutes to read • Edit Online

The filter structure used to limit lobby search results to only those lobbies owned by the player's friends.

public class LobbySearchFriendsFilter

Properties
NAME DESC RIP T IO N

IncludeFacebookFriends A flag which includes the player's Facebook friends list if their
PlayFab account is linked to their Facebook account.

IncludeSteamFriends A flag which includes the player's Steam friends list if their
PlayFab account is linked to their Steam account.

IncludeXboxFriendsToken An Xbox Live token that, when provided, includes the


player's Xbox Live friends list if their PlayFab account is linked
to their Xbox Live account.

Remarks
Regardless of which external friend lists are included when constructing this filter, friends from the PlayFab
friends list will always be included.

See Also
namespace PlayFab.Multiplayer
LobbySearchFriendsFilter.IncludeFacebookFriends
property
5/24/2022 • 2 minutes to read • Edit Online

A flag which includes the player's Facebook friends list if their PlayFab account is linked to their Facebook
account.

public bool IncludeFacebookFriends { get; set; }

See Also
class LobbySearchFriendsFilter
namespace PlayFab.Multiplayer
LobbySearchFriendsFilter.IncludeSteamFriends
property
5/24/2022 • 2 minutes to read • Edit Online

A flag which includes the player's Steam friends list if their PlayFab account is linked to their Steam account.

public bool IncludeSteamFriends { get; set; }

See Also
class LobbySearchFriendsFilter
namespace PlayFab.Multiplayer
LobbySearchFriendsFilter.IncludeXboxFriendsToken
property
5/24/2022 • 2 minutes to read • Edit Online

An Xbox Live token that, when provided, includes the player's Xbox Live friends list if their PlayFab account is
linked to their Xbox Live account.

public string IncludeXboxFriendsToken { get; set; }

Remarks
To retrieve this token, make a POST request to "https://playfabapi.com" with an empty request body using one
of the GetTokenAndSignature APIs provided by Xbox Live.
GetTokenAndSignature APIs are provided natively as part of the Microsoft Game Core Development Kit (GDK).
On all other platforms, these APIs are provided via the Xbox Authentication Library API (XAL).

See Also
class LobbySearchFriendsFilter
namespace PlayFab.Multiplayer
Class LobbySearchResult
5/24/2022 • 2 minutes to read • Edit Online

An entry in the collection of lobby search results received upon successful completion of a FindLobbies
operation.

public class LobbySearchResult

Properties
NAME DESC RIP T IO N

ConnectionString The connection string of the found lobby.

CurrentMemberCount The current number of members that are present in this


lobby.

Friends The friends in the found lobby, if the lobby search was
performed with a LobbySearchFriendsFilter .

LobbyId The ID of the found lobby.

MaxMemberCount The maximum number of members that can be present in


this lobby.

OwnerEntity The current owner of the lobby.

SearchProperties The search properties associated with this lobby.

See Also
namespace PlayFab.Multiplayer
LobbySearchResult.ConnectionString property
5/24/2022 • 2 minutes to read • Edit Online

The connection string of the found lobby.

public string ConnectionString { get; }

Remarks
LobbySearchResult.ConnectionString can be null. In this case, an invite is required to join.

See Also
class LobbySearchResult
namespace PlayFab.Multiplayer
LobbySearchResult.CurrentMemberCount property
5/24/2022 • 2 minutes to read • Edit Online

The current number of members that are present in this lobby.

public uint CurrentMemberCount { get; }

See Also
class LobbySearchResult
namespace PlayFab.Multiplayer
LobbySearchResult.Friends property
5/24/2022 • 2 minutes to read • Edit Online

The friends in the found lobby, if the lobby search was performed with a LobbySearchFriendsFilter .

public IList<PFEntityKey> Friends { get; }

Remarks
If the lobby search which generated this search result was not performed with a LobbySearchFriendsFilter , this
value will always be 0.
In some multiplayer social networks, friendship is a unidirectional relationship. One user may "follow" another
or be their friend, but the same is not necessarily true in the reverse direction. Friends will only be returned in
this search result when a bidirectional friendship exists. That is, the user querying for the lobby and the user in
the lobby must both be friends with each other.

See Also
class PFEntityKey
class LobbySearchResult
namespace PlayFab.Multiplayer
LobbySearchResult.LobbyId property
5/24/2022 • 2 minutes to read • Edit Online

The ID of the found lobby.

public string LobbyId { get; }

See Also
class LobbySearchResult
namespace PlayFab.Multiplayer
LobbySearchResult.MaxMemberCount property
5/24/2022 • 2 minutes to read • Edit Online

The maximum number of members that can be present in this lobby.

public uint MaxMemberCount { get; }

See Also
class LobbySearchResult
namespace PlayFab.Multiplayer
LobbySearchResult.OwnerEntity property
5/24/2022 • 2 minutes to read • Edit Online

The current owner of the lobby.

public PFEntityKey OwnerEntity { get; }

Remarks
LobbySearchResult.OwnerEntity may be null if the lobby doesn't currently have an owner.

See Also
class PFEntityKey
class LobbySearchResult
namespace PlayFab.Multiplayer
LobbySearchResult.SearchProperties property
5/24/2022 • 2 minutes to read • Edit Online

The search properties associated with this lobby.

public IDictionary<string, string> SearchProperties { get; }

See Also
class LobbySearchResult
namespace PlayFab.Multiplayer
Class MatchmakingMatchDetails
5/24/2022 • 2 minutes to read • Edit Online

public class MatchmakingMatchDetails

Properties
NAME DESC RIP T IO N

LobbyArrangementString The lobby arrangement string associated with the match.

MatchId The ID of the match.

Members The members that have been matched together.

RegionPreferences Preferred regions for the match, sorted from most to least
preferred.

See Also
namespace PlayFab.Multiplayer
MatchmakingMatchDetails.LobbyArrangementString
property
5/24/2022 • 2 minutes to read • Edit Online

The lobby arrangement string associated with the match.

public string LobbyArrangementString { get; }

Remarks
This connection string can optionally be used with JoinArrangedLobby to join a lobby associated with this match
result. The lobby is not created until a user attempts to join it.

See Also
class MatchmakingMatchDetails
namespace PlayFab.Multiplayer
MatchmakingMatchDetails.MatchId property
5/24/2022 • 2 minutes to read • Edit Online

The ID of the match.

public string MatchId { get; }

See Also
class MatchmakingMatchDetails
namespace PlayFab.Multiplayer
MatchmakingMatchDetails.Members property
5/24/2022 • 2 minutes to read • Edit Online

The members that have been matched together.

public IList<MatchmakingTicketMatchMember> Members { get; }

See Also
class MatchmakingTicketMatchMember
class MatchmakingMatchDetails
namespace PlayFab.Multiplayer
MatchmakingMatchDetails.RegionPreferences
property
5/24/2022 • 2 minutes to read • Edit Online

Preferred regions for the match, sorted from most to least preferred.

public IList<string> RegionPreferences { get; }

See Also
class MatchmakingMatchDetails
namespace PlayFab.Multiplayer
Class MatchmakingTicket
5/24/2022 • 2 minutes to read • Edit Online

public class MatchmakingTicket

Properties
NAME DESC RIP T IO N

Status The matchmaking ticket status.

TicketId The ID of the matchmaking ticket

Methods
NAME DESC RIP T IO N

Cancel Cancels the ticket.

GetMatchDetails Provides the match, if one has been found.

See Also
namespace PlayFab.Multiplayer
MatchmakingTicket.Status property
5/24/2022 • 2 minutes to read • Edit Online

The matchmaking ticket status.

public MatchmakingTicketStatus Status { get; }

See Also
enum MatchmakingTicketStatus
class MatchmakingTicket
namespace PlayFab.Multiplayer
MatchmakingTicket.TicketId property
5/24/2022 • 2 minutes to read • Edit Online

The ID of the matchmaking ticket

public string TicketId { get; }

See Also
class MatchmakingTicket
namespace PlayFab.Multiplayer
MatchmakingTicket.Cancel method
5/24/2022 • 2 minutes to read • Edit Online

Cancels the ticket.

public void Cancel()

Remarks
This method queues an asynchronous operation to cancel this matchmaking ticket. On success, a
OnMatchmakingTicketCompleted will be provided indicating that the ticket has been canceled.

This method does not guarantee the ticket will be canceled. The ticket may complete before the cancellation can
be processed, or the cancellation request may fail due to networking or service errors. If the cancellation attempt
fails but is retrievable, the library will continue to retry the cancellation. Otherwise, a
OnMatchmakingTicketCompleted will be provided that indicates the ticket failed.

See Also
class MatchmakingTicket
namespace PlayFab.Multiplayer
MatchmakingTicket.GetMatchDetails method
5/24/2022 • 2 minutes to read • Edit Online

Provides the match, if one has been found.

public MatchmakingMatchDetails GetMatchDetails()

See Also
class MatchmakingMatchDetails
class MatchmakingTicket
namespace PlayFab.Multiplayer
Class MatchmakingTicketMatchMember
5/24/2022 • 2 minutes to read • Edit Online

public class MatchmakingTicketMatchMember

Properties
NAME DESC RIP T IO N

AttributesJSON The attributes for this user in serialized JSON format.

EntityKey The Entity Key for this match member.

TeamId The team ID assigned to this match member.

See Also
namespace PlayFab.Multiplayer
MatchmakingTicketMatchMember.AttributesJSON
property
5/24/2022 • 2 minutes to read • Edit Online

The attributes for this user in serialized JSON format.

public string AttributesJSON { get; }

See Also
class MatchmakingTicketMatchMember
namespace PlayFab.Multiplayer
MatchmakingTicketMatchMember.EntityKey
property
5/24/2022 • 2 minutes to read • Edit Online

The Entity Key for this match member.

public PFEntityKey EntityKey { get; }

See Also
class PFEntityKey
class MatchmakingTicketMatchMember
namespace PlayFab.Multiplayer
MatchmakingTicketMatchMember.TeamId property
5/24/2022 • 2 minutes to read • Edit Online

The team ID assigned to this match member.

public string TeamId { get; }

Remarks
May be empty if the matchmaking queue doesn't use team rules.

See Also
class MatchmakingTicketMatchMember
namespace PlayFab.Multiplayer
Class PFEntityKey
5/24/2022 • 2 minutes to read • Edit Online

PFEntityKey data model. Combined entity type and ID structure which uniquely identifies a single entity.

public class PFEntityKey

Constructors
NAME DESC RIP T IO N

PFEntityKey Initializes a new instance of the PFEntityKey class. Pass in


a PlayFabAuthenticationContext authContext returned by a
PlayFab login method. (2 constructors)

Properties
NAME DESC RIP T IO N

Id Unique ID of the entity.

Type Entity type. See


https://docs.microsoft.com/gaming/playfab/features/data/en
tities/available-built-in-entity-types.

Remarks
For more information about entities, see https://docs.microsoft.com/gaming/playfab/features/data/entities/.

See Also
namespace PlayFab.Multiplayer
PFEntityKey constructor
5/24/2022 • 2 minutes to read • Edit Online

PFEntityKey (1 of 2)
Initializes a new instance of the PFEntityKey class. Pass in a PlayFabAuthenticationContext authContext returned
by a PlayFab login method.

public PFEntityKey(PlayFabAuthenticationContext authContext)

See Also 1
class PFEntityKey
namespace PlayFab.Multiplayer

PFEntityKey (2 of 2)
Initializes a new instance of the PFEntityKey class.

public PFEntityKey(string id, string type)

See Also 2
class PFEntityKey
namespace PlayFab.Multiplayer
PFEntityKey.Id property
5/24/2022 • 2 minutes to read • Edit Online

Unique ID of the entity.

public string Id { get; set; }

See Also
class PFEntityKey
namespace PlayFab.Multiplayer
PFEntityKey.Type property
5/24/2022 • 2 minutes to read • Edit Online

Entity type. See https://docs.microsoft.com/gaming/playfab/features/data/entities/available-built-in-entity-


types.

public string Type { get; set; }

Remarks
Player entities are typically the title_player_account type. For more information, see See
https://docs.microsoft.com/gaming/playfab/features/data/entities/available-built-in-entity-types.

See Also
class PFEntityKey
namespace PlayFab.Multiplayer
Class PlayFabMultiplayer
5/24/2022 • 3 minutes to read • Edit Online

public class PlayFabMultiplayer

Constructors
NAME DESC RIP T IO N

PlayFabMultiplayer The default constructor.

Properties
NAME DESC RIP T IO N

static IsInitialized Returns true if the library has been initialized.

static LogLevel Gets or sets the amount of logging currently enabled.

Constants
NAME DESC RIP T IO N

const LobbyClientRequestedSearchResultCountUpperLimit The maximum number of search results that client-entity


callers may request when performing a FindLobbies
operation.

const LobbyMaxLobbyPropertyCount The maximum number of concurrent properties which can


be stored for the lobby and which aren't owned by any
specific member.

const LobbyMaxMemberCountLowerLimit The minimum allowed value for


!:CreateAndJoinLobbyConfiguration.MaxMemberCount and
MaxMemberCount .

const LobbyMaxMemberCountUpperLimit The maximum allowed value for


!:CreateAndJoinLobbyConfiguration.MaxMemberCount and
MaxMemberCount .

const LobbyMaxMemberPropertyCount The maximum number of concurrent properties allowed for


each member in the lobby.

const LobbyMaxSearchPropertyCount The maximum number of concurrent search properties


which can be stored for the lobby.

Events
NAME DESC RIP T IO N

static event OnAddMemberCompleted Event triggered when a add member is completed.

static event OnError Event triggered when an there is an error calling another API
to be used for debugging purposes.

static event OnForceRemoveMemberCompleted Event triggered when a force remove member is completed.

static event OnLobbyCreateAndJoinCompleted Event triggered when a previous call to


!:PlayFabMultiplayer.CreateAndJoinLobby() completed.

static event OnLobbyDisconnected Event triggered when a client has disconnected from a lobby.

static event OnLobbyFindLobbiesCompleted Event triggered when the operation started by a previous
call to !:PlayFabMultiplayer.FindLobbies() completed.

static event OnLobbyInviteListenerStatusChanged Event triggered when an invite listener's status has changed.

static event OnLobbyInviteReceived Event triggered when an entity on this client has received an
invite to a lobby.

static event OnLobbyJoinArrangedLobbyCompleted Event triggered when the operation started by a previous
call to !:PlayFabMultiplayer.JoinArrangedLobby() completed.

static event OnLobbyJoinCompleted Event triggered when the operation started by a previous
call to !:PlayFabMultiplayer.JoinLobby() completed.

static event OnLobbyLeaveCompleted Event triggered when the operation started by a previous
call to !:Lobby.Leave() completed.

static event OnLobbyMemberAdded Event triggered when a PlayFab entity was added to a lobby
as a member.

static event OnLobbyMemberRemoved Event triggered when a PlayFab entity was removed from a
lobby as a member.

static event OnLobbyPostUpdateCompleted Event triggered when the operation started by a previous
call to !:Lobby.PostUpdate() completed.

static event OnLobbySendInviteCompleted Event triggered when the operation started by a previous
call to !:PlayFabMultiplayer.SendInvite() completed.

static event OnLobbyUpdated Event triggered when the lobby was updated.

static event OnMatchmakingTicketCompleted Event triggered when a matchmaking ticket status has
completed

static event OnMatchmakingTicketStatusChanged Event triggered when a matchmaking ticket status has
changed.

Delegates
NAME DESC RIP T IO N

delegate OnAddMemberCompletedHandler Handler for when the operation started by a previous call to
!:Lobby.AddMember completed

delegate OnErrorEventHandler Handler for when there is an error calling another API to be
used for debugging purposes.

delegate OnForceRemoveMemberCompletedHandler Handler for when the operation started by a previous call to
!:PlayFabLobby.ForceRemoveMember() completed.

delegate OnLobbyCreateAndJoinCompletedHandler Handler for when the operation started by a previous call to
!:PlayFabMultiplayer.CreateAndJoinLobby() completed.

delegate OnLobbyDisconnectedHandler Handler for when the client has disconnected from a lobby.

delegate OnLobbyFindLobbiesCompletedHandler Handler for when the operation started by a previous call to
!:PlayFabMultiplayer.FindLobbies() completed.

delegate OnLobbyInviteListenerStatusChangedHandler Handler for when an invite listener's status has changed.

delegate OnLobbyInviteReceivedHandler Handler for when an entity on this client has received an
invite to a lobby.

delegate OnLobbyJoinArrangedLobbyCompletedHandler Handler for when the operation started by a previous call to
!:PlayFabMultiplayer.JoinArrangedLobby() completed.

delegate OnLobbyJoinCompletedHandler Handler for when the operation started by a previous call to
!:PlayFabMultiplayer.JoinLobby() completed.

delegate OnLobbyLeaveCompletedHandler Handler for when the operation started by a previous call to
!:Lobby.Leave() completed.

delegate OnLobbyMemberAddedHandler Handler for when a local PlayFab entity was added to lobby
as a member.

delegate OnLobbyMemberRemovedHandler Handler for when a PlayFab entity was removed from a
lobby as a member.

delegate OnLobbyPostUpdateCompletedHandler Handler for when the operation started by a previous call to
!:Lobby.PostUpdate() completed.

delegate OnLobbySendInviteCompletedHandler Handler for when the operation started by a previous call to
!:PlayFabMultiplayer.SendInvite() completed.

delegate OnLobbyUpdatedHandler Handler for when a lobby was updated.

delegate OnMatchmakingTicketCompletedHandler Handler for when a matchmaking ticket status has changed.

delegate OnMatchmakingTicketStatusChangedHandler Handler for when a matchmaking ticket status has changed.

Methods
NAME DESC RIP T IO N

static CreateAndJoinLobby (2 methods)

static CreateMatchmakingTicket Creates a matchmaking ticket for one or more local users. (3
methods)

static FindLobbies (2 methods)

static GetLobbyInviteListenerStatus Retrieve the status of the entity's invite listener. (2 methods)

static Initialize Initializes an instance of the PlayFab Multiplayer library.

static JoinArrangedLobby (2 methods)

static JoinLobby (2 methods)

static JoinMatchmakingTicketFromId Joins one or more multiple local users to a matchmaking


ticket using a ticket ID and queue name. (2 methods)

static ProcessLobbyStateChanges

static ProcessMatchmakingStateChanges

static SetEntityToken Sets the token that should be used for authentication when
performing library actions on behalf of an entity. If a token
has previously been set for the entity, this replaces its
previous token. (2 methods)

static StartListeningForLobbyInvites Enables the Lobby invite listener for a given entity. (2
methods)

static StopListeningForLobbyInvites Disables the Lobby invite listener for a given entity. (2
methods)

static Uninitialize Immediately reclaims all resources associated with all


Multiplayer library objects.

See Also
namespace PlayFab.Multiplayer
PlayFabMultiplayer constructor
5/24/2022 • 2 minutes to read • Edit Online

The default constructor.

public PlayFabMultiplayer()

See Also
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.IsInitialized property
5/24/2022 • 2 minutes to read • Edit Online

Returns true if the library has been initialized.

public static bool IsInitialized { get; }

See Also
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.LogLevel property
5/24/2022 • 2 minutes to read • Edit Online

Gets or sets the amount of logging currently enabled.

public static LogLevelType LogLevel { get; set; }

See Also
enum LogLevelType
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.LobbyClientRequestedSearchResultCountUpperLimit
field
5/24/2022 • 2 minutes to read • Edit Online

The maximum number of search results that client-entity callers may request when performing a FindLobbies
operation.

public const uint LobbyClientRequestedSearchResultCountUpperLimit;

See Also
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.LobbyMaxLobbyPropertyCount
field
5/24/2022 • 2 minutes to read • Edit Online

The maximum number of concurrent properties which can be stored for the lobby and which aren't owned by
any specific member.

public const uint LobbyMaxLobbyPropertyCount;

See Also
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.LobbyMaxMemberCountLowerLimit
field
5/24/2022 • 2 minutes to read • Edit Online

The minimum allowed value for !:CreateAndJoinLobbyConfiguration.MaxMemberCount and MaxMemberCount .

public const uint LobbyMaxMemberCountLowerLimit;

See Also
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.LobbyMaxMemberCountUpperLimit
field
5/24/2022 • 2 minutes to read • Edit Online

The maximum allowed value for !:CreateAndJoinLobbyConfiguration.MaxMemberCount and MaxMemberCount .

public const uint LobbyMaxMemberCountUpperLimit;

See Also
class PlayFabMultiplayer
PlayFabMultiplayer.LobbyMaxMemberPropertyCount
field
5/24/2022 • 2 minutes to read • Edit Online

The maximum number of concurrent properties allowed for each member in the lobby.

public const uint LobbyMaxMemberPropertyCount;

See Also
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.LobbyMaxSearchPropertyCount
field
5/24/2022 • 2 minutes to read • Edit Online

The maximum number of concurrent search properties which can be stored for the lobby.

public const uint LobbyMaxSearchPropertyCount;

See Also
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.OnAddMemberCompleted
event
5/24/2022 • 2 minutes to read • Edit Online

Event triggered when a add member is completed.

public static event OnAddMemberCompletedHandler OnAddMemberCompleted;

See Also
delegate OnAddMemberCompletedHandler
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.OnError event
5/24/2022 • 2 minutes to read • Edit Online

Event triggered when an there is an error calling another API to be used for debugging purposes.

public static event OnErrorEventHandler OnError;

See Also
delegate OnErrorEventHandler
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.OnForceRemoveMemberCompleted
event
5/24/2022 • 2 minutes to read • Edit Online

Event triggered when a force remove member is completed.

public static event OnForceRemoveMemberCompletedHandler OnForceRemoveMemberCompleted;

See Also
delegate OnForceRemoveMemberCompletedHandler
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.OnLobbyCreateAndJoinCompleted
event
5/24/2022 • 2 minutes to read • Edit Online

Event triggered when a previous call to !:PlayFabMultiplayer.CreateAndJoinLobby() completed.

public static event OnLobbyCreateAndJoinCompletedHandler OnLobbyCreateAndJoinCompleted;

See Also
delegate OnLobbyCreateAndJoinCompletedHandler
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.OnLobbyDisconnected event
5/24/2022 • 2 minutes to read • Edit Online

Event triggered when a client has disconnected from a lobby.

public static event OnLobbyDisconnectedHandler OnLobbyDisconnected;

See Also
delegate OnLobbyDisconnectedHandler
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.OnLobbyFindLobbiesCompleted
event
5/24/2022 • 2 minutes to read • Edit Online

Event triggered when the operation started by a previous call to !:PlayFabMultiplayer.FindLobbies() completed.

public static event OnLobbyFindLobbiesCompletedHandler OnLobbyFindLobbiesCompleted;

See Also
delegate OnLobbyFindLobbiesCompletedHandler
class PlayFabMultiplayer
PlayFabMultiplayer.OnLobbyInviteListenerStatusChanged
event
5/24/2022 • 2 minutes to read • Edit Online

Event triggered when an invite listener's status has changed.

public static event OnLobbyInviteListenerStatusChangedHandler OnLobbyInviteListenerStatusChanged;

See Also
delegate OnLobbyInviteListenerStatusChangedHandler
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.OnLobbyInviteReceived event
5/24/2022 • 2 minutes to read • Edit Online

Event triggered when an entity on this client has received an invite to a lobby.

public static event OnLobbyInviteReceivedHandler OnLobbyInviteReceived;

See Also
delegate OnLobbyInviteReceivedHandler
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.OnLobbyJoinArrangedLobbyCompleted
event
5/24/2022 • 2 minutes to read • Edit Online

Event triggered when the operation started by a previous call to !:PlayFabMultiplayer.JoinArrangedLobby()


completed.

public static event OnLobbyJoinArrangedLobbyCompletedHandler OnLobbyJoinArrangedLobbyCompleted;

See Also
delegate OnLobbyJoinArrangedLobbyCompletedHandler
class PlayFabMultiplayer
PlayFabMultiplayer.OnLobbyJoinCompleted event
5/24/2022 • 2 minutes to read • Edit Online

Event triggered when the operation started by a previous call to !:PlayFabMultiplayer.JoinLobby() completed.

public static event OnLobbyJoinCompletedHandler OnLobbyJoinCompleted;

See Also
delegate OnLobbyJoinCompletedHandler
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.OnLobbyLeaveCompleted event
5/24/2022 • 2 minutes to read • Edit Online

Event triggered when the operation started by a previous call to !:Lobby.Leave() completed.

public static event OnLobbyLeaveCompletedHandler OnLobbyLeaveCompleted;

See Also
delegate OnLobbyLeaveCompletedHandler
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.OnLobbyMemberAdded event
5/24/2022 • 2 minutes to read • Edit Online

Event triggered when a PlayFab entity was added to a lobby as a member.

public static event OnLobbyMemberAddedHandler OnLobbyMemberAdded;

See Also
delegate OnLobbyMemberAddedHandler
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.OnLobbyMemberRemoved
event
5/24/2022 • 2 minutes to read • Edit Online

Event triggered when a PlayFab entity was removed from a lobby as a member.

public static event OnLobbyMemberRemovedHandler OnLobbyMemberRemoved;

See Also
delegate OnLobbyMemberRemovedHandler
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.OnLobbyPostUpdateCompleted
event
5/24/2022 • 2 minutes to read • Edit Online

Event triggered when the operation started by a previous call to !:Lobby.PostUpdate() completed.

public static event OnLobbyPostUpdateCompletedHandler OnLobbyPostUpdateCompleted;

See Also
delegate OnLobbyPostUpdateCompletedHandler
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.OnLobbySendInviteCompleted
event
5/24/2022 • 2 minutes to read • Edit Online

Event triggered when the operation started by a previous call to !:PlayFabMultiplayer.SendInvite() completed.

public static event OnLobbySendInviteCompletedHandler OnLobbySendInviteCompleted;

See Also
delegate OnLobbySendInviteCompletedHandler
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.OnLobbyUpdated event
5/24/2022 • 2 minutes to read • Edit Online

Event triggered when the lobby was updated.

public static event OnLobbyUpdatedHandler OnLobbyUpdated;

See Also
delegate OnLobbyUpdatedHandler
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.OnMatchmakingTicketCompleted
event
5/24/2022 • 2 minutes to read • Edit Online

Event triggered when a matchmaking ticket status has completed

public static event OnMatchmakingTicketCompletedHandler OnMatchmakingTicketCompleted;

See Also
delegate OnMatchmakingTicketCompletedHandler
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.OnMatchmakingTicketStatusChanged
event
5/24/2022 • 2 minutes to read • Edit Online

Event triggered when a matchmaking ticket status has changed.

public static event OnMatchmakingTicketStatusChangedHandler OnMatchmakingTicketStatusChanged;

See Also
delegate OnMatchmakingTicketStatusChangedHandler
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.OnAddMemberCompletedHandler
delegate
5/24/2022 • 2 minutes to read • Edit Online

Handler for when the operation started by a previous call to !:Lobby.AddMember completed

public delegate void OnAddMemberCompletedHandler(Lobby lobby, PFEntityKey localUser, int result);

PA RA M ET ER DESC RIP T IO N

lobby The lobby involved with the operation.

localUser The member entity which has added to the lobby.

result Indicates that the AddMember operation succeeded or


provides the reason that it failed.

Remarks
OnLobbyMemberAdded event fires anytime any member is added to the lobby (remote or local).
OnAddMemberCompleted event only fires when you invoke !:PlayFabMultiplayer.AddMember which allows you to
add additional members to the lobby. The first local member was the one who created the lobby, it will fire the
OnLobbyCreateAndJoinCompleted event. If the local member is using JoinLobby , it will fire the
OnLobbyJoinCompleted event. If the local member is using JoinArrangedLobby , it will fire the
OnLobbyJoinArrangedLobbyCompleted event.

See Also
class Lobby
class PFEntityKey
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.OnErrorEventHandler delegate
5/24/2022 • 2 minutes to read • Edit Online

Handler for when there is an error calling another API to be used for debugging purposes.

public delegate void OnErrorEventHandler(PlayFabMultiplayerErrorArgs args);

PA RA M ET ER DESC RIP T IO N

args The error args containing the error message and error code

See Also
class PlayFabMultiplayerErrorArgs
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.OnForceRemoveMemberCompletedHandler
delegate
5/24/2022 • 2 minutes to read • Edit Online

Handler for when the operation started by a previous call to !:PlayFabLobby.ForceRemoveMember() completed.

public delegate void OnForceRemoveMemberCompletedHandler(Lobby lobby, PFEntityKey targetMember,


int result);

PA RA M ET ER DESC RIP T IO N

lobby The lobby involved with the operation.

targetMember The member entity which is the target to the force remove.

result Indicates that the ForceRemoveMember operation


succeeded or provides the reason that it failed.

See Also
class Lobby
class PFEntityKey
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.OnLobbyCreateAndJoinCompletedHandler
delegate
5/24/2022 • 2 minutes to read • Edit Online

Handler for when the operation started by a previous call to !:PlayFabMultiplayer.CreateAndJoinLobby()


completed.

public delegate void OnLobbyCreateAndJoinCompletedHandler(Lobby lobby, int result);

PA RA M ET ER DESC RIP T IO N

lobby The lobby that was created and joined.

result Indicates that the CreateAndJoinLobby operation Succeeded


or provides the reason that it failed.

See Also
class Lobby
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.OnLobbyDisconnectedHandler
delegate
5/24/2022 • 2 minutes to read • Edit Online

Handler for when the client has disconnected from a lobby.

public delegate void OnLobbyDisconnectedHandler(Lobby lobby);

PA RA M ET ER DESC RIP T IO N

lobby The lobby that was disconnected.

See Also
class Lobby
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.OnLobbyFindLobbiesCompletedHandler
delegate
5/24/2022 • 2 minutes to read • Edit Online

Handler for when the operation started by a previous call to !:PlayFabMultiplayer.FindLobbies() completed.

public delegate void OnLobbyFindLobbiesCompletedHandler(IList<LobbySearchResult> searchResults,


PFEntityKey searchingEntity, int result);

PA RA M ET ER DESC RIP T IO N

searchResults The results returned by the search operation.

searchingEntity The entity provided to the call associated with this state
change.

result Indicates that the search lobbies operation Succeeded or


provides the reason that it failed.

See Also
class LobbySearchResult
class PFEntityKey
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.OnLobbyInviteListenerStatusChangedHandler
delegate
5/24/2022 • 2 minutes to read • Edit Online

Handler for when an invite listener's status has changed.

public delegate void OnLobbyInviteListenerStatusChangedHandler(PFEntityKey listeningEntity,


LobbyInviteListenerStatus newStatus);

PA RA M ET ER DESC RIP T IO N

listeningEntity The entity associated with the invite listener.

newStatus Value representing the current status of an invite listener.

See Also
class PFEntityKey
enum LobbyInviteListenerStatus
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.OnLobbyInviteReceivedHandler
delegate
5/24/2022 • 2 minutes to read • Edit Online

Handler for when an entity on this client has received an invite to a lobby.

public delegate void OnLobbyInviteReceivedHandler(PFEntityKey listeningEntity,


PFEntityKey invitingEntity, string connectionString);

PA RA M ET ER DESC RIP T IO N

listeningEntity The entity which is listening for invites and which has been
invited.

invitingEntity The entity which has invited the listeningEntity to a


lobby.

connectionString The connection string of the lobby to which the


listeningEntity has been invited.

See Also
class PFEntityKey
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.OnLobbyJoinArrangedLobbyCompletedHandler
delegate
5/24/2022 • 2 minutes to read • Edit Online

Handler for when the operation started by a previous call to !:PlayFabMultiplayer.JoinArrangedLobby()


completed.

public delegate void OnLobbyJoinArrangedLobbyCompletedHandler(Lobby lobby, PFEntityKey newMember,


int result);

PA RA M ET ER DESC RIP T IO N

lobby The lobby involved with the operation.

newMember The local member entity provided to the call associated with
this state change which is joining this lobby.

result Indicates that the JoinArrangedLobby operation Succeeded


or provides the reason that it failed.

Remarks
OnLobbyMemberAdded event fires anytime any member is added to the lobby (remote or local).
OnAddMemberCompleted event only fires when you invoke !:PlayFabMultiplayer.AddMember which allows you to
add additional members to the lobby. The first local member was the one who created the lobby, it will fire the
OnLobbyCreateAndJoinCompleted event. If the local member is using JoinLobby , it will fire the
OnLobbyJoinCompleted event. If the local member is using JoinArrangedLobby , it will fire the
OnLobbyJoinArrangedLobbyCompleted event.

See Also
class Lobby
class PFEntityKey
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.OnLobbyJoinCompletedHandler
delegate
5/24/2022 • 2 minutes to read • Edit Online

Handler for when the operation started by a previous call to !:PlayFabMultiplayer.JoinLobby() completed.

public delegate void OnLobbyJoinCompletedHandler(Lobby lobby, PFEntityKey newMember, int result);

PA RA M ET ER DESC RIP T IO N

lobby The lobby involved with the operation.

newMember The local member entity provided to the call associated with
this state change which is joining this lobby.

result Indicates that the JoinArrangedLobby operation Succeeded


or provides the reason that it failed.

Remarks
OnLobbyMemberAdded event fires anytime any member is added to the lobby (remote or local).
OnAddMemberCompleted event only fires when you invoke !:PlayFabMultiplayer.AddMember which allows you to
add additional members to the lobby. The first local member was the one who created the lobby, it will fire the
OnLobbyCreateAndJoinCompleted event. If the local member is using JoinLobby , it will fire the
OnLobbyJoinCompleted event. If the local member is using JoinArrangedLobby , it will fire the
OnLobbyJoinArrangedLobbyCompleted event.

See Also
class Lobby
class PFEntityKey
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.OnLobbyLeaveCompletedHandler
delegate
5/24/2022 • 2 minutes to read • Edit Online

Handler for when the operation started by a previous call to !:Lobby.Leave() completed.

public delegate void OnLobbyLeaveCompletedHandler(Lobby lobby, PFEntityKey localUser);

PA RA M ET ER DESC RIP T IO N

lobby The lobby involved with the operation.

localUser The local user provided to the call associated with this state
change. May be null. If this value is null it signifies that the
title requested all local members leave the specified lobby.

See Also
class Lobby
class PFEntityKey
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.OnLobbyMemberAddedHandler
delegate
5/24/2022 • 2 minutes to read • Edit Online

Handler for when a local PlayFab entity was added to lobby as a member.

public delegate void OnLobbyMemberAddedHandler(Lobby lobby, PFEntityKey member);

PA RA M ET ER DESC RIP T IO N

lobby The lobby involved with the operation.

member The PlayFab entity which is now a member of the lobby.

Remarks
OnLobbyMemberAdded event fires anytime any member is added to the lobby (remote or local).
OnAddMemberCompleted event only fires when you invoke !:PlayFabMultiplayer.AddMember which allows you to
add additional members to the lobby. The first local member was the one who created the lobby, it will fire the
OnLobbyCreateAndJoinCompleted event. If the local member is using JoinLobby , it will fire the
OnLobbyJoinCompleted event. If the local member is using JoinArrangedLobby , it will fire the
OnLobbyJoinArrangedLobbyCompleted event.

See Also
class Lobby
class PFEntityKey
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.OnLobbyMemberRemovedHandler
delegate
5/24/2022 • 2 minutes to read • Edit Online

Handler for when a PlayFab entity was removed from a lobby as a member.

public delegate void OnLobbyMemberRemovedHandler(Lobby lobby, PFEntityKey member,


LobbyMemberRemovedReason reason);

PA RA M ET ER DESC RIP T IO N

lobby The lobby involved with the operation.

member The member entity which has been removed from the lobby.

reason The reason member was removed from the lobby.

See Also
class Lobby
class PFEntityKey
enum LobbyMemberRemovedReason
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.OnLobbyPostUpdateCompletedHandler
delegate
5/24/2022 • 2 minutes to read • Edit Online

Handler for when the operation started by a previous call to !:Lobby.PostUpdate() completed.

public delegate void OnLobbyPostUpdateCompletedHandler(Lobby lobby, PFEntityKey localUser,


int result);

PA RA M ET ER DESC RIP T IO N

lobby The lobby involved with the operation.

localUser The local user provided to the call associated with this state
change.

result Indicates that the update operation Succeeded or provides


the reason that it failed.

See Also
class Lobby
class PFEntityKey
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.OnLobbySendInviteCompletedHandler
delegate
5/24/2022 • 2 minutes to read • Edit Online

Handler for when the operation started by a previous call to !:PlayFabMultiplayer.SendInvite() completed.

public delegate void OnLobbySendInviteCompletedHandler(Lobby lobby, PFEntityKey sender,


PFEntityKey invitee, int result);

PA RA M ET ER DESC RIP T IO N

lobby The lobby involved with the operation.

sender The local user which attempted to send the invite.

invitee The entity which was invited.

result Indicates that the SendInvite operation Succeeded or


provides the reason that it failed.

See Also
class Lobby
class PFEntityKey
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.OnLobbyUpdatedHandler
delegate
5/24/2022 • 2 minutes to read • Edit Online

Handler for when a lobby was updated.


This state change signifies that the lobby has updated and provides hints as to which values have changed.
Multiple updates may be provided by a single call to !:ProcessingLobbyStateChanges(). All state reflected by
these updates will become available simultaneously when ProcessingLobbyStateChanges() is called, so the
updates can be reconciled either individually or as a batch.

public delegate void OnLobbyUpdatedHandler(Lobby lobby, bool ownerUpdated, bool maxMembersUpdated,


bool accessPolicyUpdated, bool membershipLockUpdated, IList<string> updatedSearchPropertyKeys,
IList<string> updatedLobbyPropertyKeys, IList<LobbyMemberUpdateSummary> memberUpdates);

PA RA M ET ER DESC RIP T IO N

lobby The lobby involved with the operation.

ownerUpdated A flag indicating if the lobby's owner was updated.

maxMembersUpdated A flag indicating if the maximum number of members


allowed in the lobby has been updated.

accessPolicyUpdated A flag indicating if the lobby's access policy was updated.

membershipLockUpdated A flag indicating if the lobby's membership lock has updated.

updatedSearchPropertyKeys The keys of the search properties which have been updated.

updatedLobbyPropertyKeys The keys of the lobby properties which have been updated.

memberUpdates The set of member updates.

See Also
class Lobby
class LobbyMemberUpdateSummary
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.OnMatchmakingTicketCompletedHandler
delegate
5/24/2022 • 2 minutes to read • Edit Online

Handler for when a matchmaking ticket status has changed.

public delegate void OnMatchmakingTicketCompletedHandler(MatchmakingTicket ticket, int result);

PA RA M ET ER DESC RIP T IO N

ticket The matchmaking ticket whose status changed.

result Indicates whether the ticket found a match or provides the


high-level reason that it failed.

See Also
class MatchmakingTicket
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.OnMatchmakingTicketStatusChangedHandler
delegate
5/24/2022 • 2 minutes to read • Edit Online

Handler for when a matchmaking ticket status has changed.

public delegate void OnMatchmakingTicketStatusChangedHandler(MatchmakingTicket ticket);

PA RA M ET ER DESC RIP T IO N

ticket The matchmaking ticket whose status changed.

See Also
class MatchmakingTicket
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.CreateAndJoinLobby method
5/24/2022 • 2 minutes to read • Edit Online

PlayFabMultiplayer.CreateAndJoinLobby (1 of 2)
public static Lobby CreateAndJoinLobby(PFEntityKey creator,
LobbyCreateConfiguration createConfiguration, LobbyJoinConfiguration joinConfiguration)

See Also 1
class Lobby
class PFEntityKey
class LobbyCreateConfiguration
class LobbyJoinConfiguration
class PlayFabMultiplayer
namespace PlayFab.Multiplayer

PlayFabMultiplayer.CreateAndJoinLobby (2 of 2)
public static Lobby CreateAndJoinLobby(PlayFabAuthenticationContext creator,
LobbyCreateConfiguration createConfiguration, LobbyJoinConfiguration joinConfiguration)

See Also 2
class Lobby
class LobbyCreateConfiguration
class LobbyJoinConfiguration
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.CreateMatchmakingTicket
method
5/24/2022 • 3 minutes to read • Edit Online

PlayFabMultiplayer.CreateMatchmakingTicket (1 of 3)
Creates a matchmaking ticket for one or more local users.

public static MatchmakingTicket CreateMatchmakingTicket(IList<MatchUser> localUsers,


string queueName, uint timeoutInSeconds = 120)

PA RA M ET ER DESC RIP T IO N

localUsers The array of local users along with local user attributes to
include in the ticket.

queueName The queue to which the ticket belongs.

timeoutInSeconds How long to attempt matchmaking the ticket, in seconds.


Defaults to 120 seconds

Return Value 1
The resulting ticket object.

Remarks 1
The library automatically, and asynchronously, will submit all local users on a ticket to the matchmaking service.
Each time the ticket status changes, a OnMatchmakingTicketStatusChanged will be provided. The ticket status can
be queried at any time via Status . The ticket immediately starts in the MatchmakingTicketStatus.Creating state.
When the ticket has completed, a OnMatchmakingTicketStatusChanged will be provided. At that point, a match will
have been found or the ticket stopped due to failure. On success, the match that was found can be queried via
GetMatchDetails .

All existing tickets in which a local user is a member will be canceled as part of this operation.
A match can't be found until all remote users specified in the membersToMatchWith field of the configuration
parameter have joined the ticket via !:PlayFabMultiplayer.JoinMatchmakingTicketFromId().

See Also 1
class MatchmakingTicket
struct MatchUser
class PlayFabMultiplayer
namespace PlayFab.Multiplayer

PlayFabMultiplayer.CreateMatchmakingTicket (2 of 3)
Creates a matchmaking ticket for one or more local users.

public static MatchmakingTicket CreateMatchmakingTicket(MatchUser localUser, string queueName,


uint timeoutInSeconds = 120)

PA RA M ET ER DESC RIP T IO N

localUser The local user along with local user attributes to include in
the ticket.

queueName The queue to which the ticket belongs.

timeoutInSeconds How long to attempt matchmaking the ticket, in seconds.


Defaults to 120 seconds

Return Value 2
The resulting ticket object.

Remarks 2
The library automatically, and asynchronously, will submit all local users on a ticket to the matchmaking service.
Each time the ticket status changes, a OnMatchmakingTicketStatusChanged will be provided. The ticket status can
be queried at any time via Status . The ticket immediately starts in the MatchmakingTicketStatus.Creating state.
When the ticket has completed, a OnMatchmakingTicketStatusChanged will be provided. At that point, a match will
have been found or the ticket stopped due to failure. On success, the match that was found can be queried via
GetMatchDetails .

All existing tickets in which a local user is a member will be canceled as part of this operation.
A match can't be found until all remote users specified in the membersToMatchWith field of the configuration
parameter have joined the ticket via !:PlayFabMultiplayer.JoinMatchmakingTicketFromId().

See Also 2
class MatchmakingTicket
struct MatchUser
class PlayFabMultiplayer
namespace PlayFab.Multiplayer

PlayFabMultiplayer.CreateMatchmakingTicket (3 of 3)
Creates a matchmaking ticket for one or more local users.

public static MatchmakingTicket CreateMatchmakingTicket(IList<MatchUser> localUsers,


string queueName, List<PFEntityKey> membersToMatchWith, uint timeoutInSeconds = 120)

PA RA M ET ER DESC RIP T IO N

localUsers The array of local users along with local user attributes to
include in the ticket.
PA RA M ET ER DESC RIP T IO N

queueName The queue to which the ticket belongs.

membersToMatchWith The other specific users expected to join the ticket.

timeoutInSeconds How long to attempt matchmaking the ticket, in seconds.


Defaults to 120 seconds

Return Value 3
The resulting ticket object.

Remarks 3
The library automatically, and asynchronously, will submit all local users on a ticket to the matchmaking service.
Each time the ticket status changes, a OnMatchmakingTicketStatusChanged will be provided. The ticket status can
be queried at any time via Status . The ticket immediately starts in the MatchmakingTicketStatus.Creating state.
When the ticket has completed, a OnMatchmakingTicketStatusChanged will be provided. At that point, a match will
have been found or the ticket stopped due to failure. On success, the match that was found can be queried via
GetMatchDetails .

All existing tickets in which a local user is a member will be canceled as part of this operation.
A match can't be found until all remote users specified in the membersToMatchWith field of the configuration
parameter have joined the ticket via !:PlayFabMultiplayer.JoinMatchmakingTicketFromId().

See Also 3
class MatchmakingTicket
struct MatchUser
class PFEntityKey
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.FindLobbies method
5/24/2022 • 2 minutes to read • Edit Online

PlayFabMultiplayer.FindLobbies (1 of 2)
public static void FindLobbies(PFEntityKey searchingEntity,
LobbySearchConfiguration searchConfiguration)

See Also 1
class PFEntityKey
class LobbySearchConfiguration
class PlayFabMultiplayer
namespace PlayFab.Multiplayer

PlayFabMultiplayer.FindLobbies (2 of 2)
public static void FindLobbies(PlayFabAuthenticationContext searchingEntity,
LobbySearchConfiguration searchConfiguration)

See Also 2
class LobbySearchConfiguration
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.GetLobbyInviteListenerStatus
method
5/24/2022 • 2 minutes to read • Edit Online

PlayFabMultiplayer.GetLobbyInviteListenerStatus (1 of 2)
Retrieve the status of the entity's invite listener.

public static LobbyInviteListenerStatus GetLobbyInviteListenerStatus(PFEntityKey listeningEntity)

PA RA M ET ER DESC RIP T IO N

listeningEntity The entity which is listening for invites.

Return Value 1
The output status value.

Remarks 1
This value is used to understand the state of an entity's invite listener. If the invite listener encounters a fatal
error, non-fatal error, or diagnostic change, the listener's status value will reflect it.
When the invite listener's status changes, a OnLobbyInviteListenerStatusChanged struct will be provided by
!:PlayFabMultiplayer.OnMultiplayerStartProcessingLobby. This method can then be called to retrieve the latest
status and act accordingly.

See Also 1
enum LobbyInviteListenerStatus
class PFEntityKey
class PlayFabMultiplayer
namespace PlayFab.Multiplayer

PlayFabMultiplayer.GetLobbyInviteListenerStatus (2 of 2)
Retrieve the status of the entity's invite listener.

public static LobbyInviteListenerStatus GetLobbyInviteListenerStatus(


PlayFabAuthenticationContext listeningEntity)

PA RA M ET ER DESC RIP T IO N

listeningEntity The entity which is listening for invites.


Return Value 2
The output status value.

Remarks 2
This value is used to understand the state of an entity's invite listener. If the invite listener encounters a fatal
error, non-fatal error, or diagnostic change, the listener's status value will reflect it.
When the invite listener's status changes, a OnLobbyInviteListenerStatusChanged struct will be provided by
!:PlayFabMultiplayer.OnMultiplayerStartProcessingLobby. This method can then be called to retrieve the latest
status and act accordingly.

See Also 2
enum LobbyInviteListenerStatus
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.Initialize method
5/24/2022 • 2 minutes to read • Edit Online

Initializes an instance of the PlayFab Multiplayer library.

public static void Initialize()

Remarks
Initialize() cannot be called again without a subsequent Uninitialize call.
Every call to Initialize() should have a corresponding Uninitialize() call.
The playFabTitleId is read from PlayFab's static PlayFabSettings asset. It can be changed Using Unity menu,
PlayFab | MakePlayFabSharedSettings menu. It must be the same PlayFab Title ID used to acquire the PlayFab
Entity Keys and Entity Tokens that will be passed to !:PlayFabMultiplayer.SetEntityToken().

See Also
method Uninitialize
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.JoinArrangedLobby method
5/24/2022 • 2 minutes to read • Edit Online

PlayFabMultiplayer.JoinArrangedLobby (1 of 2)
public static Lobby JoinArrangedLobby(PFEntityKey newMember, string arrangementString,
LobbyArrangedJoinConfiguration config)

See Also 1
class Lobby
class PFEntityKey
class LobbyArrangedJoinConfiguration
class PlayFabMultiplayer
namespace PlayFab.Multiplayer

PlayFabMultiplayer.JoinArrangedLobby (2 of 2)
public static Lobby JoinArrangedLobby(PlayFabAuthenticationContext newMember,
string arrangementString, LobbyArrangedJoinConfiguration config)

See Also 2
class Lobby
class LobbyArrangedJoinConfiguration
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.JoinLobby method
5/24/2022 • 2 minutes to read • Edit Online

PlayFabMultiplayer.JoinLobby (1 of 2)
public static Lobby JoinLobby(PFEntityKey newMember, string connectionString,
IDictionary<string, string> memberKeyValuePairs)

See Also 1
class Lobby
class PFEntityKey
class PlayFabMultiplayer
namespace PlayFab.Multiplayer

PlayFabMultiplayer.JoinLobby (2 of 2)
public static Lobby JoinLobby(PlayFabAuthenticationContext newMember, string connectionString,
IDictionary<string, string> memberKeyValuePairs)

See Also 2
class Lobby
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.JoinMatchmakingTicketFromId
method
5/24/2022 • 2 minutes to read • Edit Online

PlayFabMultiplayer.JoinMatchmakingTicketFromId (1 of 2)
Joins one or more multiple local users to a matchmaking ticket using a ticket ID and queue name.

public static MatchmakingTicket JoinMatchmakingTicketFromId(IList<MatchUser> localUsers,


string ticketId, string queueName, IList<PFEntityKey> membersToMatchWith)

PA RA M ET ER DESC RIP T IO N

localUsers The array of local users along with local user attributes to
include in the ticket.

ticketId The ID of the ticket to join.

queueName The queue to which the ticket belongs.

membersToMatchWith The other specific users expected to join the ticket.

Return Value 1
The resulting ticket object.

Remarks 1
The library automatically, and asynchronously, will submit all local users to join the ticket on the matchmaking
service. Each time the ticket status changes, a OnMatchmakingTicketStatusChanged will be provided. The ticket
status can be quered at any time via Status . The ticket immediately starts in the
MatchmakingTicketStatus.Joining state.

When the ticket has completed, a OnMatchmakingTicketStatusChanged will be provided. At that point, a match will
have been found or the ticket stopped due to failure. On success, the match that was found can be queried via
GetMatchDetails .

All existing tickets in which a local user is a member will be canceled as part of this operation.

See Also 1
class MatchmakingTicket
struct MatchUser
class PFEntityKey
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.JoinMatchmakingTicketFromId (2 of 2)
Joins one or more multiple local users to a matchmaking ticket using a ticket ID and queue name.

public static MatchmakingTicket JoinMatchmakingTicketFromId(MatchUser localUser, string ticketId,


string queueName, IList<PFEntityKey> membersToMatchWith)

PA RA M ET ER DESC RIP T IO N

localUser The local user along with local user attributes to include in
the ticket.

ticketId The ID of the ticket to join.

queueName The queue to which the ticket belongs.

membersToMatchWith The other specific users expected to join the ticket.

Return Value 2
The resulting ticket object.

Remarks 2
The library automatically, and asynchronously, will submit all local users to join the ticket on the matchmaking
service. Each time the ticket status changes, a OnMatchmakingTicketStatusChanged will be provided. The ticket
status can be quered at any time via Status . The ticket immediately starts in the
MatchmakingTicketStatus.Joining state.

When the ticket has completed, a OnMatchmakingTicketStatusChanged will be provided. At that point, a match will
have been found or the ticket stopped due to failure. On success, the match that was found can be queried via
GetMatchDetails .

All existing tickets in which a local user is a member will be canceled as part of this operation.

See Also 2
class MatchmakingTicket
struct MatchUser
class PFEntityKey
class PlayFabMultiplayer
PlayFabMultiplayer.ProcessLobbyStateChanges
method
5/24/2022 • 2 minutes to read • Edit Online

public static void ProcessLobbyStateChanges()

See Also
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.ProcessMatchmakingStateChanges
method
5/24/2022 • 2 minutes to read • Edit Online

public static void ProcessMatchmakingStateChanges()

See Also
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.SetEntityToken method
5/24/2022 • 4 minutes to read • Edit Online

PlayFabMultiplayer.SetEntityToken (1 of 2)
Sets the token that should be used for authentication when performing library actions on behalf of an entity. If a
token has previously been set for the entity, this replaces its previous token.

public static void SetEntityToken(PlayFabAuthenticationContext localMember)

PA RA M ET ER DESC RIP T IO N

localMember The PlayFab PlayFabAuthenticationContext containing the


entity and token.

Remarks 1
This method takes a PlayFabAuthenticationContext authContext returned by a PlayFab login method. When the
library performs operations on behalf of an entity that require authentication or authorization, such as creating
or updating a lobby, the library will look up a token associated with the entity to use for the operation. If no
token has previously been set for the entity, the operation will synchronously fail. During the asynchronous
operation, the PlayFab service will validate that the token is valid, is not expired, is associated with the Entity ID
provided, and is authorized to perform the operation. If these conditions aren't met, the operation will fail.
A PlayFab Entity Key and Entity Token can be obtained from the output of a PlayFab login operation and then
provided as input to this method.
The provided authContext must have been acquired using the same PlayFab Title ID that was passed to
Initialize .

The Multiplayer library makes a copy of the supplied PlayFab Entity Token for use in subsequent operations that
require authentication or authorization of the local user, such as !:PlayFabMultiplayer.CreateAndJoinLobby(). If
the token provided to this call is expired or otherwise invalid, operations that require a valid token will fail. A
new, valid token can be provided to the Multiplayer library by calling this method again using the same entity
key.
The caller is responsible for monitoring the expiration of the entity token provided to this method. When the
token is nearing or past the expiration time a new token should be obtained by performing a PlayFab login
operation and provided to the Multiplayer library by calling this method again. It is recommended to acquire a
new token when the previously supplied token is halfway through its validity period. On platforms that may
enter a low power state or otherwise cause the application to pause execution for a long time, preventing the
token from being refreshed before it expires, the token should be checked for expiration once execution
resumes.

See Also 1
method Initialize
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.SetEntityToken (2 of 2)
Sets the token that should be used for authentication when performing library actions on behalf of an entity. If a
token has previously been set for the entity, this replaces its previous token.

public static void SetEntityToken(PFEntityKey localMember, string entityToken)

PA RA M ET ER DESC RIP T IO N

localMember The PlayFab Entity Key to associate with a token.

entityToken The PlayFab Entity token to associate with an entity.

Remarks 2
This method takes a PlayFab Entity Key as localMember and a PlayFab Entity Token as entityToken. When the
library performs operations on behalf of an entity that require authentication or authorization, such as creating
or updating a lobby, the library will look up a token associated with the entity to use for the operation. If no
token has previously been set for the entity, the operation will synchronously fail. During the asynchronous
operation, the PlayFab service will validate that the token is valid, is not expired, is associated with the Entity ID
provided, and is authorized to perform the operation. If these conditions aren't met, the operation will fail.
A PlayFab Entity Key and Entity Token can be obtained from the output of a PlayFab login operation and then
provided as input to this method.
The provided localMember and entityToken must have been acquired using the same PlayFab Title ID that was
passed to Initialize .
The Multiplayer library makes a copy of the supplied PlayFab Entity Token for use in subsequent operations that
require authentication or authorization of the local user, such as !:PlayFabMultiplayer.CreateAndJoinLobby(). If
the token provided to this call is expired or otherwise invalid, operations that require a valid token will fail. A
new, valid token can be provided to the Multiplayer library by calling this method again using the same entity
key.
The caller is responsible for monitoring the expiration of the entity token provided to this method. When the
token is nearing or past the expiration time a new token should be obtained by performing a PlayFab login
operation and provided to the Multiplayer library by calling this method again. It is recommended to acquire a
new token when the previously supplied token is halfway through its validity period. On platforms that may
enter a low power state or otherwise cause the application to pause execution for a long time, preventing the
token from being refreshed before it expires, the token should be checked for expiration once execution
resumes.

See Also 2
method Initialize
class PFEntityKey
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.StartListeningForLobbyInvites
method
5/24/2022 • 2 minutes to read • Edit Online

PlayFabMultiplayer.StartListeningForLobbyInvites (1 of 2)
Enables the Lobby invite listener for a given entity.

public static void StartListeningForLobbyInvites(PFEntityKey listeningEntity)

PA RA M ET ER DESC RIP T IO N

listeningEntity The entity which will listen for invites.

Remarks 1
This operation will synchronously start listening for invites on behalf of the provided entity. When invites are
received, they will be provided via OnLobbyInviteReceived events. When the status of the invite listener changes,
notifications will be provided via OnLobbyInviteListenerStatusChanged events.
Only invites sent after the listener has been started will be received on this client. Invites sent while this listener
is not active will not be queued.
Invite listening is, by default, disabled for all entities. This method should be called for each local entity that the
title wants to receive Lobby invites.
Lobby invites and this invite listener are unrelated to and unaffected by platform invite mechanisms.
This method may only be called if the Lobby invite listener is not already enabled for the given entity.

See Also 1
class PFEntityKey
class PlayFabMultiplayer
namespace PlayFab.Multiplayer

PlayFabMultiplayer.StartListeningForLobbyInvites (2 of 2)
Enables the Lobby invite listener for a given entity.

public static void StartListeningForLobbyInvites(PlayFabAuthenticationContext listeningEntity)

PA RA M ET ER DESC RIP T IO N

listeningEntity The entity which will listen for invites.


Remarks 2
This operation will synchronously start listening for invites on behalf of the provided entity. When invites are
received, they will be provided via OnLobbyInviteReceived events. When the status of the invite listener changes,
notifications will be provided via OnLobbyInviteListenerStatusChanged events.
Only invites sent after the listener has been started will be received on this client. Invites sent while this listener
is not active will not be queued.
Invite listening is, by default, disabled for all entities. This method should be called for each local entity that the
title wants to receive Lobby invites.
Lobby invites and this invite listener are unrelated to and unaffected by platform invite mechanisms.
This method may only be called if the Lobby invite listener is not already enabled for the given entity.

See Also 2
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.StopListeningForLobbyInvites
method
5/24/2022 • 2 minutes to read • Edit Online

PlayFabMultiplayer.StopListeningForLobbyInvites (1 of 2)
Disables the Lobby invite listener for a given entity.

public static void StopListeningForLobbyInvites(PFEntityKey listeningEntity)

PA RA M ET ER DESC RIP T IO N

listeningEntity The entity which is listening for invites.

Remarks 1
This operation will synchronously stop listening for invites on behalf of the provided entity.
Invite notifications which have already been queued internally will still be provided via the next call to
!:PlayFabMultiplayer.ProcessingLobbyStateChanges().
Lobby invites and this invite listener are unrelated to and unaffected by platform invite mechanisms.
This method may only be called if the Lobby invite listener is already enabled for the given entity.

See Also 1
class PFEntityKey
class PlayFabMultiplayer
namespace PlayFab.Multiplayer

PlayFabMultiplayer.StopListeningForLobbyInvites (2 of 2)
Disables the Lobby invite listener for a given entity.

public static void StopListeningForLobbyInvites(PlayFabAuthenticationContext listeningEntity)

PA RA M ET ER DESC RIP T IO N

listeningEntity The entity which is listening for invites.

Remarks 2
This operation will synchronously stop listening for invites on behalf of the provided entity.
Invite notifications which have already been queued internally will still be provided via the next call to
!:PlayFabMultiplayer.ProcessingLobbyStateChanges().
Lobby invites and this invite listener are unrelated to and unaffected by platform invite mechanisms.
This method may only be called if the Lobby invite listener is already enabled for the given entity.

See Also 2
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
PlayFabMultiplayer.Uninitialize method
5/24/2022 • 2 minutes to read • Edit Online

Immediately reclaims all resources associated with all Multiplayer library objects.

public static void Uninitialize()

Remarks
If local users were participating in a Lobby, they are removed (it appears to remote lobby clients as if network
connectivity to these users has been lost), so best practice is to call !:Lobby.Leave() on all lobbies and wait for the
corresponding OnLobbyLeaveCompleted event to have the local users exit any existing lobbies.
This method is not thread-safe and may not be called concurrently with other Multiplayer library methods. After
calling this method, all Multiplayer library state is invalidated.
Titles using the Microsoft Game Core version of the Multiplayer library must listen for app state notifications via
the RegisterAppStateChangeNotification API. When the app is suspended, the title must call Uninitialize(). When
the app is resumed, the title must wait for the Game Core networking stack to be ready and then re-initialize the
Multiplayer library by calling Initialize().
Every call to Initialize should have a corresponding Uninitialize() call.

See Also
method Initialize
class PlayFabMultiplayer
namespace PlayFab.Multiplayer
Class PlayFabMultiplayerErrorArgs
5/24/2022 • 2 minutes to read • Edit Online

An event argument class representing a PFMultiplayer error.

public class PlayFabMultiplayerErrorArgs : EventArgs

Properties
NAME DESC RIP T IO N

Code Gets the error code indicating the result of the operation.

Message Gets a call-specific error message with debug information.


This message is not localized as it is meant to be used for
debugging only.

See Also
namespace PlayFab.Multiplayer
PlayFabMultiplayerErrorArgs.Code property
5/24/2022 • 2 minutes to read • Edit Online

Gets the error code indicating the result of the operation.

public int Code { get; protected set; }

See Also
class PlayFabMultiplayerErrorArgs
namespace PlayFab.Multiplayer
PlayFabMultiplayerErrorArgs.Message property
5/24/2022 • 2 minutes to read • Edit Online

Gets a call-specific error message with debug information. This message is not localized as it is meant to be
used for debugging only.

public string Message { get; protected set; }

See Also
class PlayFabMultiplayerErrorArgs
namespace PlayFab.Multiplayer
Class PlayfabMultiplayerEventProcessor
5/24/2022 • 2 minutes to read • Edit Online

public class PlayfabMultiplayerEventProcessor : MonoBehaviour

Constructors
NAME DESC RIP T IO N

PlayfabMultiplayerEventProcessor The default constructor.

See Also
namespace PlayFab.Multiplayer
PlayfabMultiplayerEventProcessor constructor
5/24/2022 • 2 minutes to read • Edit Online

The default constructor.

public PlayfabMultiplayerEventProcessor()

See Also
class PlayfabMultiplayerEventProcessor
namespace PlayFab.Multiplayer
Struct MatchUser
5/24/2022 • 2 minutes to read • Edit Online

public struct MatchUser

Constructors
NAME DESC RIP T IO N

MatchUser Initializes a new instance of the MatchUser struct. (2


constructors)

Properties
NAME DESC RIP T IO N

LocalUser The local user to join to the ticket.

LocalUserJsonAttributesJSON The local user attributes as JSON string. There should be one
attribute string for each local user. Each attribute string
should either be an empty string or a serialized JSON object.
For example,
{"player_color":"blue","player_role":"tank"} .

See Also
namespace PlayFab.Multiplayer
MatchUser constructor
5/24/2022 • 2 minutes to read • Edit Online

MatchUser (1 of 2)
Initializes a new instance of the MatchUser struct.

public MatchUser(PFEntityKey localUser, string localUserJsonAttributesJSON)

PA RA M ET ER DESC RIP T IO N

localUser The local user to join to the ticket.

localUserJsonAttributesJSON The array of local user attribute strings. There should be one
attribute string for each local user. Each attribute string
should either be an empty string or a serialized JSON object.
For example,
{"player_color":"blue","player_role":"tank"} .

See Also 1
class PFEntityKey
struct MatchUser
namespace PlayFab.Multiplayer

MatchUser (2 of 2)
Initializes a new instance of the MatchUser struct.

public MatchUser(PlayFabAuthenticationContext localUser, string localUserJsonAttributesJSON)

PA RA M ET ER DESC RIP T IO N

localUser The local user to join to the ticket.

localUserJsonAttributesJSON The array of local user attribute strings. There should be one
attribute string for each local user. Each attribute string
should either be an empty string or a serialized JSON object.
For example,
{"player_color":"blue","player_role":"tank"} .

See Also 2
struct MatchUser
namespace PlayFab.Multiplayer
MatchUser.LocalUser property
5/24/2022 • 2 minutes to read • Edit Online

The local user to join to the ticket.

public PFEntityKey LocalUser { get; set; }

See Also
class PFEntityKey
struct MatchUser
namespace PlayFab.Multiplayer
MatchUser.LocalUserJsonAttributesJSON property
5/24/2022 • 2 minutes to read • Edit Online

The local user attributes as JSON string. There should be one attribute string for each local user. Each attribute
string should either be an empty string or a serialized JSON object. For example,
{"player_color":"blue","player_role":"tank"} .

public string LocalUserJsonAttributesJSON { get; set; }

See Also
struct MatchUser
namespace PlayFab.Multiplayer
LobbyAccessPolicy
5/24/2022 • 2 minutes to read • Edit Online

The access policy for the lobby

public enum LobbyAccessPolicy : uint

Values
NAME VA L UE DESC RIP T IO N

Public 0 The lobby is both visible in queries and


any player may join, including invited
players.

Friends 1 The lobby and its connection string are


queryable by friends of members in
this lobby.

Private 2 The lobby is not visible in queries, and


a player must receive an invite to join.

See Also
namespace PlayFab.Multiplayer
LobbyDisconnectingReason
5/24/2022 • 2 minutes to read • Edit Online

Reasons the client no longer has access to the Lobby.

public enum LobbyDisconnectingReason : uint

Values
NAME VA L UE DESC RIP T IO N

NoLocalMembers 0 The client is no longer connected to


the lobby because none of the client's
local entities are members.

LobbyDeleted 1 The client is being disconnected from


the lobby because the lobby's server
owner has deleted the lobby.

See Also
namespace PlayFab.Multiplayer
LobbyInviteListenerStatus
5/24/2022 • 2 minutes to read • Edit Online

Values representing the current status of an invite listener.

public enum LobbyInviteListenerStatus : uint

Values
NAME VA L UE DESC RIP T IO N

NotListening 0 The invite listener has not been started


or has been stopped and is not
listening for invites.

Listening 1 The invite listener has been established


and is listening for invites.

NotAuthorized 2 The listening entity was not authorized


to establish an invite listener.

See Also
namespace PlayFab.Multiplayer
LobbyMemberRemovedReason
5/24/2022 • 2 minutes to read • Edit Online

Reasons why a member was removed from a lobby.

public enum LobbyMemberRemovedReason : uint

Values
NAME VA L UE DESC RIP T IO N

LocalUserLeftLobby 0 The local user is being removed


because the title called !:Lobby.Leave().

LocalUserForciblyRemoved 1 The local user entity was forcibly


removed by the owner.

RemoteUserLeftLobby 2 The remote user has been removed


from the lobby. It is unspecified why
they are being removed.

See Also
namespace PlayFab.Multiplayer
LobbyMembershipLock
5/24/2022 • 2 minutes to read • Edit Online

public enum LobbyMembershipLock : uint

Values
NAME VA L UE DESC RIP T IO N

Unlocked 0

Locked 1

See Also
namespace PlayFab.Multiplayer
LobbyOwnerMigrationPolicy
5/24/2022 • 2 minutes to read • Edit Online

The available policies the lobby service can use to migrate lobby ownership between members.

public enum LobbyOwnerMigrationPolicy : uint

Values
NAME VA L UE DESC RIP T IO N

Automatic 0 Once the lobby owner is disconnected,


a new owner is chosen at random from
the set of connected members.

Manual 1 Once the lobby owner is disconnected,


any member may elect themselves the
new owner.

None 2 At any point, any member may elect


themselves the owner of the lobby,
regardless of the state of the current
owner.

Server 3 The server is the owner and owner


migration is not possible.

See Also
namespace PlayFab.Multiplayer
PlayFab.Multiplayer.LogLevelType
5/24/2022 • 2 minutes to read • Edit Online

The amount of logging that is enabled.

public enum LogLevelType : uint

Values
NAME VA L UE DESC RIP T IO N

None 0 No logging

Minimal 1 Include only minimal logs

Verbose 2 Include all logs

See Also
namespace PlayFab.Multiplayer
MatchmakingTicketStatus
5/24/2022 • 2 minutes to read • Edit Online

The possible states for a matchmaking ticket.

public enum MatchmakingTicketStatus : uint

Values
NAME VA L UE DESC RIP T IO N

Creating 0 The matchmaking ticket is being


created.

Joining 1 The matchmaking ticket is being


joined.

WaitingForPlayers 2 The matchmaking ticket is waiting for


all remote users specified in the
membersToMatchWith field of its
configuration to join the ticket via
!:PlayFabMultiplayer.JoinMatchmakingT
icket().

WaitingForMatch 3 The matchmaking ticket is waiting for a


match to be found.

Matched 4 The matchmaking ticket has found a


match.

Canceled 5 The matchmaking ticket has been


canceled.

Failed 6 The matchmaking ticket failed to find a


match.

See Also
namespace PlayFab.Multiplayer
PlayStream Event Model reference
5/24/2022 • 10 minutes to read • Edit Online

These are the built-in PlayStream events which are automatically generated by PlayFab Game Services APIs and
written to the event pipeline. In addition to these events, you can create your own custom events using the
WriteEvents API.
Each event type has a set of properties that are included as part of event's data wherever it is sent. You can view
these properties and build rules for triggering actions based on their values in the PlayStream tab of the Game
Manager.

General
entity_created
This event is triggered when an entity is created.
entity_executed_cloud_script
This event is optionally triggered when an Entity CloudScript function is executed, either by calling the
ExecuteCloudScript API with the GeneratePlayStreamEvent option or triggered by a PlayStream event
action with the 'Publish results as a PlayStream Event' box checked.
entity_files_set
This event is triggered when files are attached to an entity.
entity_language_updated
This event is triggered when the language associated with an entity is changed.
entity_logged_in
This event is triggered when an entity has logged in.
entity_objects_set
This event is triggered when objects are attached to an entity.
entity_virtual_currency_balances_changed
This event is triggered when an entity's virtual currency balance changes.
group_created This event is triggered when an entity group is created.
group_deleted
This event is triggered when an entity group is deleted.
group_members_added
This event is triggered when a member is added to an entity group.
group_members_removed
This event is triggered when a member is removed from an entity group.
group_role_created
This event is triggered when a role is created for a group.
group_role_deleted
This event is triggered when a role is deleted from a group.
group_role_members_added
This event is triggered when a list of entities are added to a role within a group.
group_role_members_removed
This event is triggered when a list of entities are removed from a role within a group.
group_role_updated
This event is triggered when a role is updated within a group.
group_updated
This event is triggered when an entity group is updated.
matchmaking_match_found
This event is triggered when a group of tickets are matched together.
matchmaking_ticket_completed
This event is triggered when a matchmaking ticket reaches a completion state.
matchmaking_user_ticket_completed
This event is sent to each of the users in the completed ticket.
matchmaking_user_ticket_invite
This event is triggered when a ticket with an invited user is created. The event will be sent to the invited
user.
multiplayer_server_build_deleted
This event is triggered when a multiplayer server build is deleted.
multiplayer_server_build_region_status_changed
This event is triggered when a multiplayer server's build region status is changed.
multiplayer_server_build_region_updated
This event is triggered when a multiplayer server build region is updated.
multiplayer_server_certificate_deleted
This event is triggered when a multiplayer server certificate is deleted.
multiplayer_server_certificate_uploaded
This event is triggered when a multiplayer server certificate is uploaded.
multiplayer_server_create_build_initiated
This event is triggered when a multiplayer server build is initiated.
multiplayer_server_game_asset_deleted
This event is triggered when a multiplayer server game asset is deleted.
multiplayer_server_requested
This event is triggered when a multiplayer server shutdown is requested.
multiplayer_server_state_changed
This event is triggered when a multiplayer server's state is changed.
multiplayer_server_vm_assigned
This event is triggered when a virtual machine is assigned to a multiplayer server build.
multiplayer_server_vm_remote_user_created
This event is triggered when a multiplayer server virtual machine remote user is created.
multiplayer_server_vm_remote_user_deleted
This event is triggered when a multiplayer server virtual machine remote user is deleted.
multiplayer_server_vm_unassignment_started
This event is triggered when a virtual machine is unassigned from a multiplayer server build.
multiplayer_server_vm_unhealthy
This event is triggered when a virtual machine is found to be unhealthy.
studio_created
This event is triggered when a studio is created.
studio_user_added
This event is triggered when a user accepts a studio invitation.
studio_user_invited
This event is triggered when a user is invited to a studio.
studio_user_removed
This event is triggered when a user is removed from a studio.
tenancy_connector_onboard
This event is triggered when a tenancy connector is onboarded.
studio_tier_updated
This event is triggered when a studio tier is updated.

Character
character_consumed_item
This event is triggered when a character consumes an item from their inventory.
character_created
This event is triggered when a character is created for the first time.
character_inventory_item_added
This event is triggered when an item is granted to a character.
character_statistic_changed
This event is triggered when a character statistic is changed.
character_statistic_deleted
This event is triggered when a character statistic is deleted.
character_vc_item_purchased
This event is triggered when the character makes a purchase using virtual currency.
character_virtual_currency_balance_changed
This event is triggered when a character's virtual currency balance changes.

Partner
display_name_filtered
This event is triggered when a display name is filtered by community sift.
player_display_name_filtered
This event is triggered when a display name is filtered by community sift only if there is an associated
player EntityId for the event.
player_photon_session_authenticated
This event is triggered when a player connects to a Photon Cloud application and authenticates with
PlayFab using Photon custom authentication.

Player
auth_token_validated
This event is triggered when an email confirmation link is clicked.
title_deleted_master_player
This event is triggered when a GDPR delete is finished.
player_action_executed
This event is triggered when an action linked to a segmentation change or event rule executes on a player.
player_ad_campaign_attribution
This event is triggered by an attribution tracking Add-on when a player is matched to a paid acquisition
campaign.
player_ad_closed
This event is triggered when a player closes an ad.
player_added_title
This event is triggered when a player creates a new account for a title. Note: this event is triggered once
per title rather than once per publisher.
player_ad_ended
This event is triggered when a player finishes an ad.
player_ad_opened
This event is triggered when a player opens an ad.
player_ad_rewarded
This event is triggered when a player recieves an ad reward.
player_ad_activity_valued
Event triggered when reported value of ad view is recorded
player_ad_started
This event is triggered when a player starts an ad.
player_banned
This event is triggered when a player is banned.
player_changed_avatar
This event is triggered when a player's avatar URL is changed.
player_completed_password_reset
This event is triggered when a player completes the password reset process by visiting the link URL that
was sent to them and choosing a new password.
player_consumed_item
This event is triggered when a player consumes an item from their inventory.
player_created
This event is triggered when a player account is created for the first time. Note: this event is only
triggered once per publisher, not once per title.
player_data_exported
This event is triggered when a player's data is exported.
player_device_info
This event is triggered once after the player logs in based on the settings for your title.
player_displayname_changed
This event is triggered when a player's display name is changed.
player_executed_cloudscript
This event is optionally triggered when a CloudScript function is executed, either by calling the
ExecuteCloudScript API with the GeneratePlayStreamEvent option or triggered by a PlayStream event
action with the 'Publish results as a PlayStream Event' box checked.
player_inventory_item_added
This event is triggered when an item is granted to a player.
player_joined_lobby
This event is triggered when a player joins a multiplayer game session.
player_left_lobby
This event is triggered when a player leaves a multiplayer game session.
player_linked_account
This event is triggered when a new authentication method is linked to a player's account.
player_logged_in
This event is triggered when a player logs in.
player_matched_with_lobby
This event is triggered when a player is assigned to a game lobby and issued a connection ticket, before
the player has connected to the game lobby.
player_password_reset_link_sent
This event is triggered when a player is sent a link to reset their password.
player_paid_for_purchase
This event is triggered when the second step of the payment process completes, paying for the purchase.
player_ranked_on_leaderboard_version
This event is triggered for the top-ranked players on a leaderboard when the leaderboard version
changes (e.g. when a leaderboard statistic version is incremented). The maximum number of leaderboard
entries for which the event is generated is controlled by the "Leaderboard version change top rank events
sent" title limit.
player_realmoney_purchase
This event is triggered when a player makes a real money purchase, and generates revenue for the game.
player_receipt_validation
This event is triggered when a player attempts to make a real money purchase and the purchase receipt
is being validated.
player_redeemed_coupon
This event is triggered when a player redeems a coupon.
player_registered_push_notifications
This event is triggered when a player registers for push notifications.
player_removed_title
This event is triggered when a player account for a title is removed. Note: this event is triggered once per
title rather than once per publisher.
player_reported_as_abusive
This event is triggered when a player is reported by another player as abusive.
player_set_profile_property
This event is triggered when PlayFab makes an internal adjustment to a player profile.
player_started_purchase
This event is triggered when a player starts a purchase.
player_statistic_changed
This event is triggered when a player statistic is changed.
player_statistic_deleted
This event is triggered when a player statistic is deleted.
player_tag_added
This event is triggered when a tag is added to a player profile.
player_tag_removed
This event is triggered when a tag is removed from a player profile.
player_triggered_action_executed_cloudscript
This event is triggered when a CloudScript function is run as the result of a PlayStream action, and the
'Publish results as a PlayStream Event' box was checked.
player_unlinked_account
This event is triggered when an authentication method is unlinked from a player's account.
player_updated_contact_email
This event is triggered when a player updates a contact email on their profile.
player_vc_item_purchased
This event is triggered when the player makes a purchase using virtual currency.
player_verified_contact_email
This event is triggered when a contact email is verified for a player.
player_virtual_currency_balance_changed
This event is triggered when a player's virtual currency balance changes.
sent_push_notification
This event is triggered when a push notification is sent or fails to be sent to a player.
sent_email
This event is triggered when an email is sent or fails to send to a player.

Session
client_focus_change
This event is triggered every time the application enters or exits focus on the player's device.
client_session_start
This event is triggered when a new client session starts.
gamelobby_ended
This event is triggered when a multiplayer game lobby ends.
gamelobby_started
This event is triggered when a multiplayer game lobby starts.
gameserverhost_started
This event is triggered when a multiplayer game lobby starts.
gameserverhost_stopped
This event is triggered when a multiplayer game lobby stops.
session_ended
This event is triggered when a session ends
session_started
This event is triggered when a session starts.

Title
title_aborted_task
This event is triggered when a task instance is aborted.
title_added_cloudscript
This event is triggered when new CloudScript is uploaded to PlayFab.
title_game_build_added
This event is triggered when a new game build is uploaded for a game title.
title_api_settings_changed
This event is triggered when an API Features setting is changed for the title.
title_catalog_updated
This event is triggered when a catalog is changed.
title_client_rate_limited_alert
This event is triggered when a single IP address generates too many API calls to PlayFab and is throttled.
title_completed_task
This event is triggered when a scheduled task has completed
title_created_task
This event is triggered when a task is created.
title_deleted
This event is triggered when a game title is deleted.
title_deleted_task
This event is triggered when a task is deleted.
title_exceeded_limit
This event is triggererd when a title exceeds a service limit and receives an error.
title_high_error_rate_alert
This event is triggered when a game title experiences a high rate of errors.
title_initiated_player_password_reset
This event is triggered when a title initiates the account recovery process for a player.
title_limit_changed
This event is triggered when a title changes a service limit.
title_game_build_modified
This event is triggered when any of the game build settings are modified.
title_news_updated
This event is triggered when a title news is created or updated.
title_permission_policy_changed
This event is triggered when an update occurs to a a title's permission policies.
title_profile_view_constraints_changed
This event is triggered when a profile view constraint is changed for the title.
title_published_cloudscript
An inactive revision of CloudScript has been made into the active 'live' version.
title_queue_config_updated
This event is triggered when a queue config is changed.
title_requested_limit_change
This event is triggered when a title requests a service limit change.
title_saved_survey
This event is triggered when a game's survey is saved.
title_scheduled_cloudscript_executed
This event is triggered when a CloudScript function is run by a scheduled task.
title_secret_key_changed
This event is triggered when a title adds or updates a Secret Key
title_started_task
This event is triggered when a task is scheduled to run.
title_statistic_version_changed
This event is triggered when the version of a statistic changes, causing its leaderboard to reset.
title_store_updated
This event is triggered when a store is changed.
title_updated_task
This event is triggered when a task is updated.
auth_token_validated
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when an email confirmation link is clicked.

Properties
NAME TYPE DESC RIP T IO N

EmailTemplateId String The email template id, if the auth


token was sent via an email template.

TitleId String The ID of the title to which this player


event applies.

Token String The email token in the confirmation


link that was clicked.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'
NAME TYPE DESC RIP T IO N

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
character_consumed_item
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a character consumes an item from their inventory.

Properties
NAME TYPE DESC RIP T IO N

CatalogVersion String Version of the catalog from which the


consumed inventory item was created.

ItemId String ID of the catalog item from which the


consumed inventory item was created.
This can be used to look up the item
from the catalog.

ItemInstanceId String The specific ID of the item that was


consumed.

PlayerId String

PreviousUsesRemaining uint32 For multiple use items, the number of


uses that remained before the item
was consumed.

TitleId String

UsesRemaining uint32 For multiple use items, the number of


uses remaining after the item was
consumed.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.
NAME TYPE DESC RIP T IO N

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
character_created
5/24/2022 • 2 minutes to read • Edit Online

Properties
This event is triggered when a character is created for the first time.

NAME TYPE DESC RIP T IO N

CharacterName String Name of the character.

Created DateTime When the character was created.

PlayerId String

TitleId String

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'
NAME TYPE DESC RIP T IO N

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
character_inventory_item_added
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when an item is granted to a character.

Properties
NAME TYPE DESC RIP T IO N

Annotation String Optional details about the inventory


item.

BundleContents [] Catalog item IDs of any other items


granted to the character along with
this one as part of a bundle.

CatalogVersion String Catalog version in which the item that


was added is defined.

Class String Class of the item that was added.

CouponCode String Redeemed coupon (if any) that granted


the item.

DisplayName String Display name of the item that was


added.

Expiration DateTime When the item expires. The value is


null if the item does not expire.

InstanceId String Unique instance ID of the inventory


item that was added.

ItemId String Catalog item ID of the inventory item


that was added.

PlayerId String

RemainingUses uint32 How many uses the item has, if it has a


limited number of uses.

TitleId String

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N


NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
character_statistic_changed
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a character statistic is changed.

Properties
NAME TYPE DESC RIP T IO N

PlayerId String

StatisticName String Name of the statistic that changed.

StatisticPreviousValue int32 Old value of the statistic, before the


change.

StatisticValue int32 New value of the statistic, after the


change.

TitleId String

Version uint32 Version of the statistic that changed.


This is relevant for statistics that reset,
since each time the statistic resets the
version increments.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.
NAME TYPE DESC RIP T IO N

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
character_statistic_deleted
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a character statistic is deleted.

Properties
NAME TYPE DESC RIP T IO N

PlayerId String

StatisticName String Name of the statistic that was deleted.

TitleId String

Version uint32 Version of the statistic that changed.


This is relevant for statistics that reset,
since each time the statistic resets the
version increments.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.


NAME TYPE DESC RIP T IO N

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
character_vc_item_purchased
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when the character makes a purchase using virtual currency.

Properties
NAME TYPE DESC RIP T IO N

CatalogVersion String Version of the catalog from which the


item was purchased.

CurrencyCode String Currency that was used to purchase


the item.

ItemId String Identifier of the catalog item that was


purchased.

PlayerId String

PurchaseId String Unique identifier of the purchase


transaction.

Quantity int32 Quantity of items that were purchased.

StoreId String The StoreId where the item was


purchased.

TitleId String

UnitPrice uint32 Price paid per item, expressed in the


virtual currency.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.
NAME TYPE DESC RIP T IO N

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
character_virtual_currency_balance_changed
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a character's virtual currency balance changes.

Properties
NAME TYPE DESC RIP T IO N

OrderId String ID of the order that triggered the


balance changes.

PlayerId String

TitleId String

VirtualCurrencyBalance int32 New virtual currency balance after the


change.

VirtualCurrencyName String Virtual currency whose balance


changed.

VirtualCurrencyPreviousBalance int32 Old virtual currency balance before the


change.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.
NAME TYPE DESC RIP T IO N

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
client_focus_change
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered every time the application enters or exits focus on the player's device.

Properties
NAME TYPE DESC RIP T IO N

EntityLineage EntityLineage Entities that this entity is a child of.

OriginalEventId String The original unique identifier


associated with this event before it was
posted to PlayFab. The value might
differ from the EventId value, which is
assigned when the event is received by
the server.

OriginalTimestamp DateTime The original time (in UTC) associated


with this event before it was posted to
PlayFab. The value might differ from
the Timestamp value, which is set at
the time the event is received by the
server.

Payload ClientFocusChangePayload Payload that this entity is a child of.

WriterEntity EntityKey Entity that wrote this event, included


only if different than the event's entity.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.
NAME TYPE DESC RIP T IO N

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
client_session_start
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a new client session starts.


Properties

NAME TYPE DESC RIP T IO N

EntityLineage EntityLineage Entities that this entity is a child of.

OriginalEventId String The original unique identifier


associated with this event before it was
posted to PlayFab. The value might
differ from the EventId value, which is
assigned when the event is received by
the server.

OriginalTimestamp DateTime The original time (in UTC) associated


with this event before it was posted to
PlayFab. The value might differ from
the Timestamp value, which is set at
the time the event is received by the
server.

Payload ClientSessionStartPayload Payload that this entity is a child of.

WriterEntity EntityKey Entity that wrote this event, included


only if different than the event's entity.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.
NAME TYPE DESC RIP T IO N

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
entity_created
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when an entity is created.

Properties
NAME TYPE DESC RIP T IO N

EntityChain String The chain of ownership for this entity.

EntityLineage EntityLineage Entities that this entity is a child of.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.
NAME TYPE DESC RIP T IO N

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
entity_executed_cloud_script
5/24/2022 • 2 minutes to read • Edit Online

This event is optionally triggered when a CloudScript function is executed by calling the
ExecuteEntityCloudScript API. If you want the Event logged, you can pass in GeneratePlayStreamEvent.

Properties
NAME TYPE DESC RIP T IO N

CloudScriptExecutionResult ExecuteCloudScriptResult Result of the CloudScript function,


including diagnostic information that is
useful for debugging.

EntityChain String The chain of ownership for this entity.

EntityLineage EntityLineage Entities that this entity is a child of.

FunctionName String Name of the CloudScript function that


was called.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.


NAME TYPE DESC RIP T IO N

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
entity_files_set
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when files are attached to an entity.

Properties
NAME TYPE DESC RIP T IO N

EntityChain String The chain of ownership for this entity.

EntityLineage EntityLineage Entities that this entity is a child of.

Files FileSet The files that were updated.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'
NAME TYPE DESC RIP T IO N

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
entity_language_updated
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when the language associated with an entity is changed.

Properties
NAME TYPE DESC RIP T IO N

EntityChain String The chain of ownership for this entity.

EntityLineage EntityLineage Entities that this entity is a child of.

Language String Language that was updated

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'
NAME TYPE DESC RIP T IO N

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
entity_logged_in
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when an entity has logged in.

Properties
NAME TYPE DESC RIP T IO N

EntityChain String The chain of ownership for this entity.

EntityLineage EntityLineage Entities that this entity is a child of.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.
NAME TYPE DESC RIP T IO N

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
entity_objects_set
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when objects are attached to an entity.

Properties
NAME TYPE DESC RIP T IO N

EntityChain String The chain of ownership for this entity.

EntityLineage [EntityLineage](data- Entities that this entity is a child of.


types/entitylineage.md

Objects ObjectSet Objects that were updated

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'
NAME TYPE DESC RIP T IO N

HistoryPlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
entity_virtual_currency_balances_changed
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when an entity's virtual currency balance changes.

Properties
NAME TYPE DESC RIP T IO N

EntityChain String The chain of ownership for this entity.

EntityLineage EntityLineage Entities that this entity is a child of.

SequenceId String Sequence id of the balance change to


ensure updates are processed in order.

VirtualCurrencyBalances Object New virtual currency balances after the


change. Only shows currencies that
were updated.

VirtualCurrencyContainerId String Container whose balances changed.

VirtualCurrencyPreviousBalances Object Old virtual currency balances before


the change. Only shows currencies
that were updated.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.
NAME TYPE DESC RIP T IO N

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).
gamelobby_ended
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a multiplayer game lobby ends.

Properties
NAME TYPE DESC RIP T IO N

GameMode String Game mode of the game lobby the


player joined.

GameStartTime DateTime The time (in UTC) when this game


started.

Region String Region in which the game server lives


that the player joined.

ServerBuildVersion String Build version of the custom game


server running the lobby.

ServerHost String Publicly visible domain name or IPV4


address of the host running the
custom game server.

ServerHostInstanceId String Unique identifier of the machine


hosting the game lobby.

ServerIPV4Address String Publicly visible IPV4 address of the


host running the custom game server.

ServerIPV6Address String Publicly visible IPV6 address of the


host running the custom game server.

ServerPort uint32 Network port of the host assigned to


the custom game server.

Tags Object Custom tags associated with the game


lobby.

TitleId String The ID of the title associated with this


game lobby

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N


NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
gamelobby_started
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a multiplayer game lobby starts.

Properties
NAME TYPE DESC RIP T IO N

CustomCommandLineData String Custom command line arguments


passed to the server process running
the game lobby.

CustomMatchmakerEndpoint String Webhook endpoint of the custom


matchmaker (if any) that started the
game lobby.

GameMode String Game mode of the game lobby the


player joined.

GameServerData String Configuration data passed to the


server process running the game
lobby.

MaxPlayers int32 Maximum number of players that may


be connected to the game lobby.

Region String Region in which the game server lives


that the player joined.

ServerBuildVersion String Build version of the custom game


server running the lobby.

ServerHost String Publicly visible domain name or IPV4


address of the host running the
custom game server.

ServerHostInstanceId String Unique identifier of the machine


hosting the game lobby.

ServerIPV4Address String Publicly visible IPV4 address of the


host running the custom game server.

ServerIPV6Address String Publicly visible IPV6 address of the


host running the custom game server.

ServerPort uint32 Network port of the host assigned to


the custom game server.

Tags Object Custom tags associated with the game


lobby.
NAME TYPE DESC RIP T IO N

TitleId String The ID of the title associated with this


game lobby

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
gameserverhost_started
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a multiplayer game lobby starts.

Properties
NAME TYPE DESC RIP T IO N

InstanceId String Unique identifier of the host.

InstanceProvider String Server hosting provider of host


machine or VM.

InstanceType String Provider specific type of the host


machine or VM.

Region String Region in which the host is running.

ServerBuildVersion String Build version of the custom game


server installed on the host.

ServerHost String Publicly visible domain name or IPV4


address of the host.

ServerIPV4Address String Publicly visible IPV4 address of the


host.

ServerIPV6Address String Publicly visible IPV6 address of the


host.

StartTime DateTime Time that the host was started.

TitleId String The ID of the title associated with this


host

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.
NAME TYPE DESC RIP T IO N

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
gameserverhost_stopped
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a multiplayer game lobby stops.

Properties
NAME TYPE DESC RIP T IO N

InstanceId String Unique identifier of the host.

InstanceProvider String Server hosting provider of host


machine or VM.

InstanceType String Provider specific type of the host


machine or VM.

Region String Region in which the host is running.

ServerBuildVersion String Build version of the custom game


server installed on the host.

ServerHost String Publicly visible domain name or IPV4


address of the host.

ServerIPV4Address String Publicly visible IPV4 address of the


host.

ServerIPV6Address String Publicly visible IPV6 address of the


host.

StartTime DateTime Time that the host was started.

StopReason GameServerHostStopReason Reason that the host was stopped.

StopTime DateTime Time that the host was stopped.

TitleId String The ID of the title associated with this


host

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.
NAME TYPE DESC RIP T IO N

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
group_created
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when an entity group is created.

Properties
NAME TYPE DESC RIP T IO N

CreatorEntityId String The identifier for the entity that


created the group to which this event
applies.

CreatorEntityType String The type of entity that created the


group to which this event applies.

EntityChain String The chain of ownership for this entity.

EntityLineage EntityLineage Entities that this entity is a child of.

GroupName String The name of the group to which this


event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.


NAME TYPE DESC RIP T IO N

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
group_deleted
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when an entity group is deleted.

Properties
NAME TYPE DESC RIP T IO N

DeleterEntityId String The identifier for the entity that


deleted the group to which this event
applies.

DeleterEntityType String The type of entity that deleted the


group to which this event applies.

EntityChain String The chain of ownership for this entity.

EntityLineage EntityLineage Entities that this entity is a child of.

GroupName String The name of the group to which this


event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.


NAME TYPE DESC RIP T IO N

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
group_members_added
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a member is added to an entity group.

Properties
NAME TYPE DESC RIP T IO N

EntityChain String The chain of ownership for this entity.

EntityLineage EntityLineage Entities that this entity is a child of.

GroupName String The name of the group to which this


event applies.

Members Member The list of entities that were added to


the group and role to which this event
applies.

RoleId String The role ID of the role to which this


event applies.

RoleName String The display name of the role to which


this event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.
NAME TYPE DESC RIP T IO N

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
group_members_removed
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a member is removed from an entity group

Properties
NAME TYPE DESC RIP T IO N

EntityChain String The chain of ownership for this entity.

EntityLineage EntityLineage Entities that this entity is a child of.

GroupName String The name of the group to which this


event applies.

Members Member The list of entities that were removed


from the group to which this event
applies

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.


NAME TYPE DESC RIP T IO N

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
group_role_created
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a role is created for a group.

Properties
NAME TYPE DESC RIP T IO N

CreatorEntityId String The identifier for that the entity that


created the role to which this event
applies.

CreatorEntityType String The type of entity that created the role


to which this event applies.

EntityChain String The chain of ownership for this entity.

EntityLineage EntityLineage Entities that this entity is a child of.

GroupName String The name of the group to which this


event applies.

RoleId String The role ID of the role to which this


event applies.

RoleName String The display name of the role to which


this event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.
NAME TYPE DESC RIP T IO N

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
group_role_deleted
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a role is deleted from a group.

Properties
NAME TYPE DESC RIP T IO N

DeleterEntityId String The identifier for the entity that


deleted the role to which this event
applies.

DeleterEntityType String The type of entity that deleted the role


to which this event applies.

EntityChain String The chain of ownership for this entity.

EntityLineage EntityLineage Entities that this entity is a child of.

GroupName String The name of the group to which this


event applies.

RoleId String The role ID of the role to which this


event applies.

RoleName String The display name of the role to which


this event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.
NAME TYPE DESC RIP T IO N

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
group_role_members_added
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a list of entities are added to a role within a group.

Properties
NAME TYPE DESC RIP T IO N

EntityChain String The chain of ownership for this entity.

EntityLineage EntityLineage Entities that this entity is a child of.

GroupName String The name of the group to which this


event applies.

Members Member The list of entities that were added to


the group and role to which this event
applies

RoleId String The role ID of the role to which this


event applies.

RoleName String The display name of the role to which


this event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.
NAME TYPE DESC RIP T IO N

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
group_role_members_removed
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a list of entities are removed from a role within a group.

Properties
NAME TYPE DESC RIP T IO N

EntityChain String The chain of ownership for this entity.

EntityLineage EntityLineage Entities that this entity is a child of.

GroupName String The name of the group to which this


event applies.

Members Member The list of entities that were removed


from the group to which this event
applies

RoleId String The role ID of the role to which this


event applies.

RoleName String The display name of the role to which


this event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.
NAME TYPE DESC RIP T IO N

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
group_role_updated
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a role is updated within a group.

Properties
NAME TYPE DESC RIP T IO N

EntityChain String The chain of ownership for this entity.

EntityLineage EntityLineage Entities that this entity is a child of.

GroupName String The name of the group to which this


event applies.

NewValues RolePropertyValues The new values of the role's changed


properties

OldValues RolePropertyValues The previous values of the role's


changed properties

RoleId String The role ID of the role to which this


event applies.

RoleName String The display name of the role to which


this event applies.

UpdaterEntityId String The identifier for the entity that


updated the container to which this
event applies.

UpdaterEntityType String The type of entity that updated the


container to which this event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.
NAME TYPE DESC RIP T IO N

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
group_updated
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when an entity group is updated.

Properties
NAME TYPE DESC RIP T IO N

EntityChain String The chain of ownership for this entity.

EntityLineage EntityLineage Entities that this entity is a child of.

GroupName String The name of the group to which this


event applies.

NewValues GroupPropertyValues The new values of the group's changed


properties

OldValues GroupPropertyValues The previous values of the group's


changed properties

UpdaterEntityId String The identifier for the entity that


updated the group to which this event
applies.

UpdaterEntityType String The type of entity that updated the


group to which this event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.
NAME TYPE DESC RIP T IO N

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
matchmaking_match_found
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a group of tickets are matched together.

Properties
NAME TYPE DESC RIP T IO N

EntityLineage EntityLineage Entities that this entity is a child of.

Payload MatchmakingMatchFoundPayload Payload that this entity is a child of.

WriterEntity EntityKey Entity that wrote this event, included


only if different than the event's entity.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'
NAME TYPE DESC RIP T IO N

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
matchmaking_ticket_completed
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a matchmaking ticket reaches a completion state.

Properties
NAME TYPE DESC RIP T IO N

EntityLineage EntityLineage Entities that this entity is a child of.

Payload MatchmakingTicketCompletePayload Payload that this entity is a child of.

WriterEntity EntityKey Entity that wrote this event, included


only if different than the event's entity.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'
NAME TYPE DESC RIP T IO N

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
matchmaking_user_ticket_completed
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a matchmaking ticket reaches a completion state. This event is sent to each of the
users in the completed ticket

Properties
NAME TYPE DESC RIP T IO N

EntityLineage EntityLineage Entities that this entity is a child of.

Payload MatchmakingUserTicketCompletePaylo Payload that this entity is a child of.


ad

WriterEntity EntityKey Entity that wrote this event, included


only if different than the event's entity.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'
NAME TYPE DESC RIP T IO N

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
matchmaking_user_ticket_invite
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a ticket with an invited user is created. The event will be sent to the invited user.

Properties
NAME TYPE DESC RIP T IO N

EntityLineage EntityLineage Entities that this entity is a child of.

Payload MatchmakingUserTicketInvitePayload Payload that this entity is a child of.

WriterEntity EntityKey Entity that wrote this event, included


only if different than the event's entity.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'
NAME TYPE DESC RIP T IO N

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
multiplayer_server_build_deleted
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a multiplayer server build is deleted.

Properties
NAME TYPE DESC RIP T IO N

EntityLineage EntityLineage Entities that this entity is a child of.

OriginalEventId String The original unique identifier


associated with this event before it was
posted to PlayFab. The value might
differ from the EventId value, which is
assigned when the event is received by
the server.

OriginalTimestamp DateTime The original time (in UTC) associated


with this event before it was posted to
PlayFab. The value might differ from
the Timestamp value, which is set at
the time the event is received by the
server.

Payload MultiplayerServerBuildDeletedEventPa The multiplayer server build region


yload deleted event payload.

WriterEntity EntityKey Entity that wrote this event, included


only if different than the event's entity.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.
NAME TYPE DESC RIP T IO N

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
multiplayer_server_build_region_status_changed
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a multiplayer server's build region status is changed.

Properties
NAME TYPE DESC RIP T IO N

EntityLineage EntityLineage Entities that this entity is a child of.

OriginalEventId String The original unique identifier


associated with this event before it was
posted to PlayFab. The value might
differ from the EventId value, which is
assigned when the event is received by
the server.

OriginalTimestamp DateTime The original time (in UTC) associated


with this event before it was posted to
PlayFab. The value might differ from
the Timestamp value, which is set at
the time the event is received by the
server.

Payload MultiplayerServerBuildRegionStatusCh The multiplayer server build region


angedEventPayload status changed event payload.

WriterEntity EntityKey Entity that wrote this event, included


only if different than the event's entity.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.
NAME TYPE DESC RIP T IO N

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
multiplayer_server_build_region_updated
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a multiplayer server build region is updated.

Properties
NAME TYPE DESC RIP T IO N

EntityLineage EntityLineage Entities that this entity is a child of.

OriginalEventId String The original unique identifier


associated with this event before it was
posted to PlayFab. The value might
differ from the EventId value, which is
assigned when the event is received by
the server.

OriginalTimestamp DateTime The original time (in UTC) associated


with this event before it was posted to
PlayFab. The value might differ from
the Timestamp value, which is set at
the time the event is received by the
server.

Payload MultiplayerServerBuildRegionUpdatedE The multiplayer server build region


ventPayload updated event payload.

WriterEntity EntityKey Entity that wrote this event, included


only if different than the event's entity.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.
NAME TYPE DESC RIP T IO N

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
multiplayer_server_certificate_deleted
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a multiplayer server certificate is deleted.

Properties
NAME TYPE DESC RIP T IO N

EntityLineage EntityLineage Entities that this entity is a child of.

OriginalEventId String The original unique identifier


associated with this event before it was
posted to PlayFab. The value might
differ from the EventId value, which is
assigned when the event is received by
the server.

OriginalTimestamp DateTime The original time (in UTC) associated


with this event before it was posted to
PlayFab. The value might differ from
the Timestamp value, which is set at
the time the event is received by the
server.

Payload MultiplayerServerCertificateDeletedEve The multiplayer server certificate


ntPayload deleted event payload.

WriterEntity EntityKey Entity that wrote this event, included


only if different than the event's entity.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.
NAME TYPE DESC RIP T IO N

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
multiplayer_server_certificate_uploaded
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a multiplayer server certificate is uploaded.

Properties
NAME TYPE DESC RIP T IO N

EntityLineage EntityLineage Entities that this entity is a child of.

OriginalEventId String The original unique identifier


associated with this event before it was
posted to PlayFab. The value might
differ from the EventId value, which is
assigned when the event is received by
the server.

OriginalTimestamp DateTime The original time (in UTC) associated


with this event before it was posted to
PlayFab. The value might differ from
the Timestamp value, which is set at
the time the event is received by the
server.

Payload MultiplayerServerCertificateUploadedE The multiplayer server certificate


ventPayload uploaded event payload.

WriterEntity EntityKey Entity that wrote this event, included


only if different than the event's entity.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.
NAME TYPE DESC RIP T IO N

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
multiplayer_server_create_build_initiated
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a multiplayer server build is initiated.

Properties
NAME TYPE DESC RIP T IO N

EntityLineage EntityLineage Entities that this entity is a child of.

OriginalEventId String The original unique identifier


associated with this event before it was
posted to PlayFab. The value might
differ from the EventId value, which is
assigned when the event is received by
the server.

OriginalTimestamp DateTime The original time (in UTC) associated


with this event before it was posted to
PlayFab. The value might differ from
the Timestamp value, which is set at
the time the event is received by the
server.

Payload MultiplayerServerCreateBuildInitiatedE The multiplayer server create build


ventPayload initiated event payload.

WriterEntity EntityKey Entity that wrote this event, included


only if different than the event's entity.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.
NAME TYPE DESC RIP T IO N

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
multiplayer_server_game_asset_deleted
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a multiplayer server game asset is deleted.

Properties
NAME TYPE DESC RIP T IO N

EntityLineage EntityLineage Entities that this entity is a child of.

OriginalEventId String The original unique identifier


associated with this event before it was
posted to PlayFab. The value might
differ from the EventId value, which is
assigned when the event is received by
the server.

OriginalTimestamp DateTime The original time (in UTC) associated


with this event before it was posted to
PlayFab. The value might differ from
the Timestamp value, which is set at
the time the event is received by the
server.

Payload MultiplayerServerGameAssetDeletedEv The multiplayer server game asset


entPayload deleted event payload.

WriterEntity EntityKey Entity that wrote this event, included


only if different than the event's entity.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.
NAME TYPE DESC RIP T IO N

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
multiplayer_server_requested
5/24/2022 • 2 minutes to read • Edit Online

Properties
NAME TYPE DESC RIP T IO N

EntityLineage EntityLineage Entities that this entity is a child of.

OriginalEventId String The original unique identifier


associated with this event before it was
posted to PlayFab. The value might
differ from the EventId value, which is
assigned when the event is received by
the server.

OriginalTimestamp DateTime The original time (in UTC) associated


with this event before it was posted to
PlayFab. The value might differ from
the Timestamp value, which is set at
the time the event is received by the
server.

Payload MultiplayerServerRequestedEventPaylo The multiplayer server requested event


ad payload.

WriterEntity EntityKey Entity that wrote this event, included


only if different than the event's entity.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.
NAME TYPE DESC RIP T IO N

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
multiplayer_server_state_changed
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a multiplayer server's state is changed.

Properties
NAME TYPE DESC RIP T IO N

EntityLineage EntityLineage Entities that this entity is a child of.

OriginalEventId String The original unique identifier


associated with this event before it was
posted to PlayFab. The value might
differ from the EventId value, which is
assigned when the event is received by
the server.

OriginalTimestamp DateTime The original time (in UTC) associated


with this event before it was posted to
PlayFab. The value might differ from
the Timestamp value, which is set at
the time the event is received by the
server.

Payload MultiplayerServerStateChangedEventP The multiplayer server state changed


ayload event payload.

WriterEntity EntityKey Entity that wrote this event, included


only if different than the event's entity.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.
NAME TYPE DESC RIP T IO N

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
multiplayer_server_vm_assigned
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a virtual machine is assigned to a multiplayer server build.

Properties
NAME TYPE DESC RIP T IO N

EntityLineage EntityLineage Entities that this entity is a child of.

OriginalEventId String The original unique identifier


associated with this event before it was
posted to PlayFab. The value might
differ from the EventId value, which is
assigned when the event is received by
the server.

OriginalTimestamp DateTime The original time (in UTC) associated


with this event before it was posted to
PlayFab. The value might differ from
the Timestamp value, which is set at
the time the event is received by the
server.

Payload MultiplayerServerVmAssignedEventPay The multiplayer server virtual machine


load assigned event payload.

WriterEntity EntityKey Entity that wrote this event, included


only if different than the event's entity.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.
NAME TYPE DESC RIP T IO N

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
multiplayer_server_vm_remote_user_created
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a multiplayer server virtual machine remote user is created.

Properties
NAME TYPE DESC RIP T IO N

EntityLineage EntityLineage Entities that this entity is a child of.

OriginalEventId String The original unique identifier


associated with this event before it was
posted to PlayFab. The value might
differ from the EventId value, which is
assigned when the event is received by
the server.

OriginalTimestamp DateTime The original time (in UTC) associated


with this event before it was posted to
PlayFab. The value might differ from
the Timestamp value, which is set at
the time the event is received by the
server.

Payload MultiplayerServerVmRemoteUserCreat The multiplayer server virtual machine


edEventPayload remote user created event payload.

WriterEntity EntityKey Entity that wrote this event, included


only if different than the event's entity.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.
NAME TYPE DESC RIP T IO N

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
multiplayer_server_vm_remote_user_deleted
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a multiplayer server virtual machine remote user is deleted.

Properties
NAME TYPE DESC RIP T IO N

EntityLineage EntityLineage Entities that this entity is a child of.

OriginalEventId String The original unique identifier


associated with this event before it was
posted to PlayFab. The value might
differ from the EventId value, which is
assigned when the event is received by
the server.

OriginalTimestamp DateTime The original time (in UTC) associated


with this event before it was posted to
PlayFab. The value might differ from
the Timestamp value, which is set at
the time the event is received by the
server.

Payload MultiplayerServerVmRemoteUserDelet The multiplayer server virtual machine


edEventPayload remote user deleted event payload.

WriterEntity EntityKey Entity that wrote this event, included


only if different than the event's entity.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.
NAME TYPE DESC RIP T IO N

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
multiplayer_server_vm_unassignment_started
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a virtual machine is unassigned from a multiplayer server build.

Properties
NAME TYPE DESC RIP T IO N

EntityLineage EntityLineage Entities that this entity is a child of.

OriginalEventId String The original unique identifier


associated with this event before it was
posted to PlayFab. The value might
differ from the EventId value, which is
assigned when the event is received by
the server.

OriginalTimestamp DateTime The original time (in UTC) associated


with this event before it was posted to
PlayFab. The value might differ from
the Timestamp value, which is set at
the time the event is received by the
server.

Payload MultiplayerServerVmUnassignmentStar The multiplayer server virtual machine


tedEventPayload unassignment started event payload.

WriterEntity EntityKey Entity that wrote this event, included


only if different than the event's entity.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.
NAME TYPE DESC RIP T IO N

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_action_executed
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when an action linked to a segmentation change or event rule executes on a player.
Properties

NAME TYPE DESC RIP T IO N

ActionName String Name of the action that was triggered.

Error ActionExecutionError Information about the error that


occurred during execution, if it failed to
complete.

ExecutionDuration double Action execution time in milliseconds.

ExecutionResult object The object returned from the action


execution, if it completed.

ScheduledTimestamp DateTime Time that the action was scheduled for


execution.

TitleId String The ID of the title to which this player


event applies.

TriggeredTimestamp DateTime Time that the triggering event or


segmentation change occurred.

TriggeringEventRuleMatch EventRuleMatch Event rule match, if any, that triggered


the action.

TriggeringSegmentMembershipChange SegmentMembershipChange Player segmentation change, if any,


that triggered the action.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.
NAME TYPE DESC RIP T IO N

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_ad_activity_valued
5/24/2022 • 2 minutes to read • Edit Online

Event triggered when reported value of ad view is recorded

Properties
NAME TYPE DESC RIP T IO N

AdPlacementId String Id of the placement

AdPlacementName String Name of the placement

AdUnit String Ad unit type

RevenueShare double Share of the revenue for this ad view


(calculated as total revenue for
placement divided by total views for
that placement in that time window)

RewardId String Id of the reward

RewardName String Name of the reward

TitleId String The ID of the title to which this player


event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.
NAME TYPE DESC RIP T IO N

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_ad_campaign_attribution
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered by an attribution tracking Add-on when a player is matched to a paid acquisition
campaign.

Properties
NAME TYPE DESC RIP T IO N

CampaignId String The ID of the campaign, as passed in


by the attribution provider.

TitleId String The ID of the title to which this player


event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'
NAME TYPE DESC RIP T IO N

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_ad_closed
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a player closes an ad.

Properties
NAME TYPE DESC RIP T IO N

AdPlacementId String Id of the placement

AdPlacementName String Name of the placement

AdUnit String Ad unit type

RewardId String Id of the reward

RewardName String Name of the reward

TitleId String The ID of the title to which this player


event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.


NAME TYPE DESC RIP T IO N

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_ad_ended
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a player finishes an ad.

Properties
NAME TYPE DESC RIP T IO N

AdPlacementId String Id of the placement

AdPlacementName String Name of the placement

AdUnit String Ad unit type

RewardId String Id of the reward

RewardName String Name of the reward

TitleId String The ID of the title to which this player


event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.


NAME TYPE DESC RIP T IO N

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_ad_opened
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a player opens an ad.

Properties
NAME TYPE DESC RIP T IO N

AdPlacementId String Id of the placement

AdPlacementName String Name of the placement

AdUnit String Ad unit type

RewardId String Id of the reward

RewardName String Name of the reward

TitleId String The ID of the title to which this player


event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.


NAME TYPE DESC RIP T IO N

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
display_name_filtered
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a display name is filtered by community sift.

Properties
NAME TYPE DESC RIP T IO N

DisplayName String Value of the display name that was


filtered

PlayerId String If event occurs at account creation,


then no player exists yet. Otherwise,
the player whose displayname update
was filtered

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'
NAME TYPE DESC RIP T IO N

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_ad_rewarded
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a player recieves an ad reward.

Properties
NAME TYPE DESC RIP T IO N

ActionGroupDebugMessages [] Debug messages from the reward


actions

AdPlacementId String Id of the placement

AdPlacementName String Name of the placement

AdUnit String Ad unit type

RewardId String Id of the reward

RewardName String Name of the reward

TitleId String The ID of the title to which this player


event applies.

ViewsRemainingThisPeriod int32 Views this player has remaining for the


placement's window, if applicable

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.
NAME TYPE DESC RIP T IO N

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_ad_started
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a player starts an ad.

Properties
NAME TYPE DESC RIP T IO N

AdPlacementId String Id of the placement

AdPlacementName String Name of the placement

AdUnit String Ad unit type

RewardId String Id of the reward

RewardName String Name of the reward

TitleId String The ID of the title to which this player


event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.


NAME TYPE DESC RIP T IO N

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_added_title
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a player creates a new account for a title. Note: this event is triggered once per title
rather than once per publisher.

Properties
NAME TYPE DESC RIP T IO N

DisplayName String Player's display name when they added


this title.

Platform LoginIdentityProvider Authentication method used to


register player's account.

PlatformUserId String Unique ID for the player's account


associated with the Origination
authentication method.

TitleId String The ID of the title to which this player


event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.


NAME TYPE DESC RIP T IO N

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_banned
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a player is banned.

Properties
NAME TYPE DESC RIP T IO N

BanExpiration DateTime When the ban expires. The value is null


if the ban is permanent.

BanId String ID of the ban. Useful for tracking


unique bans, if the player has been
banned before.

BanReason String The reason why the player was


banned.

PermanentBan Boolean Whether this ban is permanent.

TitleId String The ID of the title to which this player


event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.
NAME TYPE DESC RIP T IO N

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_changed_avatar
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a player's avatar URL is changed.

Properties
NAME TYPE DESC RIP T IO N

ImageUrl String URL of the avatar image.

PreviousImageUrl String Previous URL of the avatar image.

TitleId String The ID of the title to which this player


event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'
NAME TYPE DESC RIP T IO N

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_completed_password_reset
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a player completes the password reset process by visiting the link URL that was
sent to them and choosing a new password.

Properties
NAME TYPE DESC RIP T IO N

CompletedFromIPAddress String IP address from which the password


reset process was completed.

CompletionTimestamp DateTime When the password reset process was


completed.

InitiatedBy PasswordResetInitiationSource Source that initiated the password


reset process.

InitiatedFromIPAddress String IP address from which the password


reset process was initiated.

InitiationTimestamp DateTime When the password reset process was


initiated.

LinkExpiration DateTime Expiration time for the password reset


link.

PasswordResetId String Unique identifier for the password


reset link. This cannot be used to
complete the reset.

RecoveryEmailAddress String Email address to which the password


reset link was sent.

TitleId String The ID of the title to which this player


event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.
NAME TYPE DESC RIP T IO N

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_consumed_item
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a player consumes an item from their inventory.

Properties
NAME TYPE DESC RIP T IO N

CatalogVersion String Version of the catalog from which the


consumed inventory item was created.

ItemId String ID of the catalog item from which the


consumed inventory item was created.
This can be used to look up the item
from the catalog.

ItemInstanceId String The specific ID of the item that was


consumed.

PreviousUsesRemaining uint32 For multiple use items, the number of


uses that remained before the item
was consumed.

TitleId String The ID of the title to which this player


event applies.

UsesRemaining uint32 For multiple use items, the number of


uses remaining after the item was
consumed.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.
NAME TYPE DESC RIP T IO N

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_created
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a player account is created for the first time. Note: this event is only triggered once
per publisher, not once per title.

Properties
NAME TYPE DESC RIP T IO N

Created DateTime When the player account was created.

PublisherId String Unique ID for the publisher account


under which this player account is
created.

TitleId String The ID of the title to which this player


event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'
NAME TYPE DESC RIP T IO N

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_data_exported
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a player's data is exported.

Properties
NAME TYPE DESC RIP T IO N

ExportDownloadUrl String URL to download the export.

JobReceiptId String Receipt ID of the export job. This


should correspond to the receipt ID
returned by the export API call.

RequestTime DateTime The time of export request.

TitleId String The ID of the title to which this player


event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.


NAME TYPE DESC RIP T IO N

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_device_info
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered once after the player logs in based on the settings for your title.

Properties
NAME TYPE DESC RIP T IO N

DeviceInfo Object

TitleId String The ID of the title to which this player


event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.
NAME TYPE DESC RIP T IO N

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_display_name_filtered
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a display name is filtered by community sift only if there is an associated player
EntityId for the event.

Properties
NAME TYPE DESC RIP T IO N

DisplayName String Value of the display name that was


filtered

TitleId String The ID of the title to which this player


event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'
NAME TYPE DESC RIP T IO N

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_displayname_changed
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a player's display name is changed.

Properties
NAME TYPE DESC RIP T IO N

DisplayName String New display name after the change.

PreviousDisplayName String Previous display name before the


change.

TitleId String The ID of the title to which this player


event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'
NAME TYPE DESC RIP T IO N

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_executed_cloudscript
5/24/2022 • 2 minutes to read • Edit Online

This event is optionally triggered when a CloudScript function is executed, either by calling the
ExecuteCloudScript API with the GeneratePlayStreamEvent option or triggered by a PlayStream event action
with the 'Publish results as a PlayStream Event' box checked.

Properties
NAME TYPE DESC RIP T IO N

CloudScriptExecutionResult ExecuteCloudScriptResult Result of the CloudScript function,


including diagnostic information that is
useful for debugging.

FunctionName String Name of the CloudScript function that


was called.

TitleId String The ID of the title to which this player


event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.


NAME TYPE DESC RIP T IO N

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_inventory_item_added
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when an item is granted to a player.

Properties
NAME TYPE DESC RIP T IO N

Annotation String Optional details about the inventory


item.

BundleContents [] Catalog item IDs of any other items


granted to the player along with this
one as part of a bundle.

CatalogVersion String Catalog version in which the item that


was added is defined.

Class String Class of the item that was added.

CouponCode String Redeemed coupon (if any) that granted


the item.

DisplayName String Display name of the item that was


added.

Expiration DateTime When the item expires. The value is


null if the item does not expire.

InstanceId String Unique instance ID of the inventory


item that was added.

ItemId String Catalog item ID of the inventory item


that was added.

RemainingUses uint32 How many uses the item has, if it has a


limited number of uses.

TitleId String The ID of the title to which this player


event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.
NAME TYPE DESC RIP T IO N

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_joined_lobby
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a player joins a multiplayer game session.

Properties
NAME TYPE DESC RIP T IO N

GameMode String Game mode of the game lobby the


player joined.

LobbyId String Unique ID of the game lobby the


player joined.

Region String Region in which the game server lives


that the player joined.

ServerBuildVersion String Build version of the custom game


server running the lobby.

ServerHost String Publicly visible domain name or IPV4


address of the machine running the
custom game server.

ServerHostInstanceId String Unique identifier of the machine


hosting the game lobby.

ServerIPV4Address String Publicly visible IPV4 address of the


machine running the custom game
server.

ServerIPV6Address String Publicly visible IPV6 address of the


machine running the custom game
server.

ServerPort uint32 Network port assigned to the custom


game server.

TitleId String The ID of the title to which this player


event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.
NAME TYPE DESC RIP T IO N

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_left_lobby
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a player leaves a multiplayer game session.

Properties
NAME TYPE DESC RIP T IO N

GameMode String Game mode of the game session the


player joined.

LobbyId String Unique ID of the game session the


player joined.

Region String Region in which the game server lives


that the player joined.

ServerBuildVersion String Build version of the custom game


server running the lobby.

ServerHost String Publicly visible domain name or IPV4


address of the machine running the
custom game server.

ServerHostInstanceId String Unique identifier of the machine


hosting the game lobby.

ServerIPV4Address String Publicly visible IPV4 address of the


machine running the custom game
server.

ServerIPV6Address String Publicly visible IPV6 address of the


machine running the custom game
server.

ServerPort uint32 Network port assigned to the custom


game server.

TitleId String The ID of the title to which this player


event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.
NAME TYPE DESC RIP T IO N

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_linked_account
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a new authentication method is linked to a player's account.

Properties
NAME TYPE DESC RIP T IO N

Email String Player's email linked with the given


provider

Origination LoginIdentityProvider Authentication method being linked to


a player's account.

OriginationUserId String Player's identity under authentication


method being linked to player's
account.

TitleId String The ID of the title to which this player


event applies.

Username String Player's username linked with the


given provider

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.
NAME TYPE DESC RIP T IO N

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_logged_in
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a player logs in.

Properties
NAME TYPE DESC RIP T IO N

Location EventLocation Player's geographic location, if known.


Location is estimated from factors such
as IP address and is not always
available or accurate.

Platform LoginIdentityProvider Authentication method used to login


the player.

PlatformUserId String Player's identity under the


authentication method used to login
the player.

PlatformUserName String The display name that's set in the


identity provider that the player is
authenticated with.

TitleId String The ID of the title to which this player


event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.
NAME TYPE DESC RIP T IO N

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_matched_with_lobby
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a player is assigned to a game lobby and issued a connection ticket, before the
player has connected to the game lobby.

Properties
NAME TYPE DESC RIP T IO N

GameMode String Game mode of the game lobby the


player was assigned to.

LobbyId String Unique ID of the game lobby the


player was assigned to.

Region String Region in which the game server lives


that the player was assigned to.

ServerBuildVersion String Build version of the custom game


server running the lobby.

ServerHost String Publicly visible domain name or IPV4


address of the machine running the
custom game server.

ServerHostInstanceId String Unique identifier of the machine


hosting the game lobby.

ServerIPV4Address String Publicly visible IPV4 address of the


machine running the custom game
server.

ServerIPV6Address String Publicly visible IPV6 address of the


machine running the custom game
server.

ServerPort uint32 Network port assigned to the custom


game server.

TitleId String The ID of the title to which this player


event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N


NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
PlayerMemberships
5/24/2022 • 2 minutes to read • Edit Online

Properties
NAME TYPE DESC RIP T IO N

MembershipId String Unique ID of the player's membership

MembershipExpiration DateTime Expiration time of the player's


membership

Subscriptions Subscriptions Subscription details


Subscriptions
5/24/2022 • 2 minutes to read • Edit Online

Properties
NAME TYPE DESC RIP T IO N

SubscriptionId String Identifier of the owned subscription

Expiration DateTime Expiration time of the subscription

Status String The current status of the subscription

InitialSubscriptionTime DateTime Origination time of the subscription

SubscriptionItemId String The id of the subscription offer

SubscriptionProvider String The store through which the


subscription is offered
player_paid_for_purchase
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when the second step of the payment process completes, paying for the purchase.

Properties
NAME TYPE DESC RIP T IO N

OrderId String Purchase order identifier.

ProviderData String Provider used for the transaction.

ProviderName String Payment provider to use to fund the


purchase.

ProviderToken String A token generated by the provider to


authenticate the request (provider-
specific).

PurchaseConfirmationPageURL String URL to the purchase provider page


that details the purchase.

PurchaseCurrency String Currency for the transaction, may be a


virtual currency or real money.

PurchasePrice uint32 Cost of the transaction.

Status TransactionStatus Status of the transaction.

TitleId String The ID of the title to which this player


event applies.

VirtualCurrencyBalances Object Current virtual currency balances for


the user.

VirtualCurrencyGrants Object Virtual currencies granted by the


transaction, if any.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.
NAME TYPE DESC RIP T IO N

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_password_reset_link_sent
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a player is sent a link to reset their password.

Properties
NAME TYPE DESC RIP T IO N

InitiatedBy PasswordResetInitiationSource Source that initiated the password


reset process.

InitiatedFromIPAddress String IP address from which the password


reset process was initiated.

LinkExpiration DateTime Expiration time for the password reset


link.

PasswordResetId String Unique identifier for the password


reset link. This cannot be used to
complete the reset.

RecoveryEmailAddress String Email address to which the password


reset link was sent.

TitleId String The ID of the title to which this player


event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.
NAME TYPE DESC RIP T IO N

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_photon_session_authenticated
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a player connects to a Photon Cloud application and authenticates with PlayFab
using Photon custom authentication.
Properties

NAME TYPE DESC RIP T IO N

PhotonApplicationId String Unique identifier of the Photon Cloud


application to which the player is
connected

PhotonApplicationType PhotonServicesEnum Type of Photon Cloud application to


which the player is connected

TitleId String The ID of the title to which this player


event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'
NAME TYPE DESC RIP T IO N

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_ranked_on_leaderboard_version
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered for the top-ranked players on a leaderboard when the leaderboard version changes (e.g.
when a leaderboard statistic version is incremented). The maximum number of leaderboard entries for which
the event is generated is controlled by the "Leaderboard version change top rank events sent" title limit.

Properties
NAME TYPE DESC RIP T IO N

LeaderboardSource LeaderboardSource Source of the values for the


leaderboard.

Rank uint32 Player's rank on the leaderboard.

TitleId String The ID of the title to which this player


event applies.

Value int32 Player's leaderboard value.

Version uint32 Version of the leaderboard on which


the player is ranked. For player statistic
leaderboards, this matches the version
of the statistic.

VersionChangeBehavior LeaderboardVersionChangeBehavior Behavior with respect to the


leaderboard values when the version
changed.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.
NAME TYPE DESC RIP T IO N

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_realmoney_purchase
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a player makes a real money purchase, and generates revenue for the game.

Properties
NAME TYPE DESC RIP T IO N

OrderId String Unique identifier of the order.

OrderTotal uint32 Total value of the purchase in the


system currency (defaults to USD).

PaymentProvider String Payment provider used to make the


purchase.

PaymentType PaymentType Type of payment used to make the


purchase.

PurchasedProduct [] The ItemIds from the catalog of the


purchased items, if applicable.

TitleId String The ID of the title to which this player


event applies.

TransactionCurrency Currency Local currency used to make the


purchase, if applicable.

TransactionId String Unique identifier of the transaction.

TransactionTotal uint32 Total value of the purchase in the local


currency used to make the purchase, if
applicable.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.
NAME TYPE DESC RIP T IO N

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_receipt_validation
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a player attempts to make a real money purchase and the purchase receipt is being
validated.

Properties
NAME TYPE DESC RIP T IO N

Error String The error that occurred during a


receipt validation.

PaymentProvider String Payment provider used to make the


purchase attempt.

PaymentType PaymentType Type of payment used to make the


purchase attempt.

ReceiptContent String The receipt data during a real money


purchase event attempt.

TitleId String The ID of the title to which this player


event applies.

Valid Boolean Indicates if the receipt is valid.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.
NAME TYPE DESC RIP T IO N

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_redeemed_coupon
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a player redeems a coupon.

Properties
NAME TYPE DESC RIP T IO N

CouponCode String Coupon code the player redeemed.

GrantedInventoryItems CouponGrantedInventoryItem Items added to the player's inventory


by redeeming the coupon.

TitleId String The ID of the title to which this player


event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'
NAME TYPE DESC RIP T IO N

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_registered_push_notifications
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a player registers for push notifications.

Properties
NAME TYPE DESC RIP T IO N

DeviceToken String Unique device token registered for


push notifications.

Platform PushNotificationPlatform Platform on which the player is


registering for push notifications.

TitleId String The ID of the title to which this player


event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'
NAME TYPE DESC RIP T IO N

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_removed_title
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a player account for a title is removed. Note: this event is triggered once per title
rather than once per publisher.

Properties
NAME TYPE DESC RIP T IO N

TitleId String The ID of the title to which this player


event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.
NAME TYPE DESC RIP T IO N

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_reported_as_abusive
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a player is reported by another player as abusive.

Properties
NAME TYPE DESC RIP T IO N

Comment String Comment submitted by the player


who made the report.

ReportedByPlayer String Player ID of the player who made the


report.

TitleId String The ID of the title to which this player


event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'
NAME TYPE DESC RIP T IO N

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_set_profile_property
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when PlayFab makes an internal adjustment to a player profile.

Properties
NAME TYPE DESC RIP T IO N

Property PlayerProfileProperty Property of the profile to be set

TitleId String The ID of the title to which this player


event applies.

Value object Value to set to

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'
NAME TYPE DESC RIP T IO N

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_started_purchase
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a player starts a purchase.

Properties
NAME TYPE DESC RIP T IO N

CatalogVersion String Catalog version for the items to be


purchased. Defaults to most recent
catalog.

Contents CartItem Cart items to be purchased.

OrderId String Purchase order identifier.

StoreId String Store through which to purchase


items. If not set, prices will be pulled
from the catalog itself.

TitleId String The ID of the title to which this player


event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.
NAME TYPE DESC RIP T IO N

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_statistic_changed
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a player statistic is changed.

Properties
NAME TYPE DESC RIP T IO N

AggregationMethod StatisticAggregationMethod Aggregation method applied for


calculating the new value of the
statistic.

StatisticId uint32 Unique ID of the statistic that


changed.

StatisticName String Name of the statistic that changed.

StatisticPreviousValue int32 Old value of the statistic, before the


change.

StatisticValue int32 New value of the statistic, after the


change.

TitleId String The ID of the title to which this player


event applies.

Version uint32 Version of the statistic that changed.


This is relevant for statistics that reset,
since each time the statistic resets the
version increments.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.
NAME TYPE DESC RIP T IO N

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_statistic_deleted
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a player statistic is deleted.

Properties
NAME TYPE DESC RIP T IO N

StatisticId uint32 Unique ID of the statistic that was


deleted.

StatisticName String Name of the statistic that was deleted.

StatisticPreviousValue int32 Old value of the statistic, before being


deleted.

TitleId String The ID of the title to which this player


event applies.

Version uint32 Version of the statistic. This is relevant


for statistics that reset, since each time
the statistic resets the version
increments.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.
NAME TYPE DESC RIP T IO N

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_tag_added
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a tag is added to a player profile.

Properties
NAME TYPE DESC RIP T IO N

Namespace String Namespace for this tag

TagName String Name of the tag that is added.

TitleId String The ID of the title to which this player


event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'
NAME TYPE DESC RIP T IO N

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_tag_removed
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a tag is removed from a player profile.

Properties
NAME TYPE DESC RIP T IO N

Namespace String Namespace for this tag

TagName String Name of the tag that is removed.

TitleId String The ID of the title to which this player


event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'
NAME TYPE DESC RIP T IO N

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_triggered_action_executed_cloudscript
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a CloudScript function is run as the result of a PlayStream action, and the 'Publish
results as a PlayStream Event' box was checked.

Properties
NAME TYPE DESC RIP T IO N

CloudScriptExecutionResult ExecuteCloudScriptResult Result of the CloudScript function,


including an error information. Useful
for debugging.

FunctionName String Name of the CloudScript function that


was called.

TitleId String The ID of the title to which this player


event applies.

TriggeringEventData object The full JSON data of the event that


triggered this CloudScript function to
run. Useful for debugging.

TriggeringEventName String Name of the event that triggered this


CloudScript function to run.

TriggeringPlayer PlayerProfile JSON data profile of the player that


triggered this CloudScript function to
run.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.
NAME TYPE DESC RIP T IO N

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_unlinked_account
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when an authentication method is unlinked from a player's account.

Properties
NAME TYPE DESC RIP T IO N

Origination LoginIdentityProvider Authentication method being unlinked


from a player's account.

OriginationUserId String Player's identity under authentication


method being unlinked from player's
account.

TitleId String The ID of the title to which this player


event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'
NAME TYPE DESC RIP T IO N

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_updated_contact_email
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a player updates a contact email on their profile.

Properties
NAME TYPE DESC RIP T IO N

EmailName String The name of the contact email that


was updated or added in the player's
profile.

NewEmailAddress String The contact email updated or added in


the player's profile.

PreviousEmailAddress String The previous contact email updated in


the player's profile.

TitleId String The ID of the title to which this player


event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.


NAME TYPE DESC RIP T IO N

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_vc_item_purchased
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when the player makes a purchase using virtual currency.

Properties
NAME TYPE DESC RIP T IO N

CatalogVersion String Version of the catalog from which the


item was purchased.

CurrencyCode String Currency that was used to purchase


the item.

ItemId String Identifier of the catalog item that was


purchased.

PurchaseId String Unique identifier of the purchase


transaction.

Quantity int32 Quantity of items that were purchased.

StoreId String The StoreId where the item was


purchased.

TitleId String The ID of the title to which this player


event applies.

UnitPrice uint32 Price paid per item, expressed in the


virtual currency.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.
NAME TYPE DESC RIP T IO N

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_verified_contact_email
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a contact email is verified for a player.

Properties
NAME TYPE DESC RIP T IO N

EmailAddress String The email address of the player's


contact email that was verified.

EmailName String The name of the player's contact email


that was verified.

TitleId String The ID of the title to which this player


event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'
NAME TYPE DESC RIP T IO N

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
player_virtual_currency_balance_changed
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a player's virtual currency balance changes.

Properties
NAME TYPE DESC RIP T IO N

OrderId String Id of the order that triggered the


balance changes

TitleId String The ID of the title to which this player


event applies.

VirtualCurrencyBalance int32 New virtual currency balance after the


change.

VirtualCurrencyName String Virtual currency whose balance


changed.

VirtualCurrencyPreviousBalance int32 Old virtual currency balance before the


change.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.
NAME TYPE DESC RIP T IO N

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
sent_email
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when an email is sent or fails to send to a player.

Properties
NAME TYPE DESC RIP T IO N

Body String The content of the email body,


truncated to 4096 characters.

EmailName String The name of the player's contact email


the email was sent to.

EmailTemplateId String The email template id during a send


email attempt.

EmailTemplateName String The email template name during a


send email attempt.

EmailTemplateType EmailTemplateType The email template type during a send


email attempt.

ErrorMessage String The error that occurred if an email


failed to send.

ErrorName String The name of the error that occurred if


an email failed to send.

Language String The language the email was sent in

Subject String The content of the email subject,


truncated to 1024 characters.

Success Boolean Indicates if the email was successfully


sent.

TitleId String The ID of the title to which this player


event applies.

Token String The auth token included in the sent


email as part of a confirmation URL.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:
NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
sent_push_notification
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a push notification is sent or fails to be sent to a player.

Properties
NAME TYPE DESC RIP T IO N

Body String The content of the push notification


body, truncated to 4096 characters.

ErrorMessage String The error that occurred if the push


notification failed to be sent.

ErrorName String The name of the error that occurred if


the push notification failed to be sent.

Language String The language the push notification was


sent in if a matching localized template
was used.

PushNotificationTemplateId String The push notification template id


during a send push notification
attempt.

PushNotificationTemplateName String The push notification template name


during a send push notification
attempt.

Subject String The content of the push notification


subject, truncated to 1024 characters.

Success Boolean Indicates whether the push notification


was successfully sent.

TitleId String The ID of the title to which this player


event applies.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.
NAME TYPE DESC RIP T IO N

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
session_ended
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a session ends

Properties
NAME TYPE DESC RIP T IO N

Crashed Boolean Whether or not the session was


marked as a crash

EndTime DateTime The time the session was explicitly


ended at, clamped to 24 hours. This
can differ significantly from the event
timestamp if the game crashed

KilobytesWritten double The total kilobytes written to the S3


file associated with this session

SessionLengthMs double The length of the session in


milliseconds

TitleId String The ID of the title associated with this


session

UserId String The ID of the user associated with this


session

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.
NAME TYPE DESC RIP T IO N

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
session_started
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a session starts.

Properties
NAME TYPE DESC RIP T IO N

TemporaryWriteUrl String The pre-signed S3 URL associated with


the session, which has PUT
permissions.

TitleId String The ID of the title associated with this


session

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'
NAME TYPE DESC RIP T IO N

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
studio_created
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a studio is created.

Properties
NAME TYPE DESC RIP T IO N

CreatorAuthenticationId String Authentication provider's id for the


user who created the studio

CreatorPlayFabId String PlayFab id of the user who created the


studio

StudioName String Name of the new studio

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'
NAME TYPE DESC RIP T IO N

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
studio_tier_updated
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a studio tier is updated.

Properties
NAME TYPE DESC RIP T IO N

ContactCompanyName String Contact Company Name

IsPayAsYouGo Boolean IsPayAsYouGo PaymentOption

IsReservedCapacity Boolean IsReservedCapacity PaymentOption

IsReservedCapacityAnnual Boolean IsReservedCapacityAnnual


PaymentOption

MonthlyMinimumUSD double Monthly Minimum Price in USD

OveragePricePerMauTiers PaymentOptionPerMauPriceTier OveragePricePerMauTiers Definitions

PaymentSystemAccountId String Payment System AccountId

PricePerMauTiers PaymentOptionPerMauPriceTier PricePerMauTiers Definitions

ReservedMAU int32 Reserved Capacity MAU

StudioIds IEnumerable_String Studio Ids

TierDisplayName String Tier Display Name

TierId String Tier Id

TransactionId String Transaction Id

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.
NAME TYPE DESC RIP T IO N

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
studio_user_added
5/24/2022 • 2 minutes to read • Edit Online

Properties
NAME TYPE DESC RIP T IO N

AuthenticationId String Authentication provider's ID for this


user

AuthenticationProvider AuthenticationProvider Authentication provider for the user

AuthenticationProviderId String Authentication provider entity id, if


needed by the provider

Email String User's email

InvitationId String Id of the invitation record if user


needed to register

PlayFabId String PlayFab ID for this user

StudioPermissions [] Array of studio permissions that were


be granted to the user

TitlePermissions Object Dictionary of title id, title permissions


that were granted to the user

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.
NAME TYPE DESC RIP T IO N

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
studio_user_invited
5/24/2022 • 2 minutes to read • Edit Online

This event is triggererd when a user is invited to a studio.

Properties
NAME TYPE DESC RIP T IO N

AuthenticationProvider AuthenticationProvider Authentication provider type required


for user to register with

AuthenticationProviderId String Authentication provider entity id, if


needed by the provider.

Email String Email the invitation was sent to

InvitationExpires DateTime Expiration of the invitation

InvitationId String Id of the invitation if user needed to


register

InvitedExistingUser Boolean Indicates if the user invited already


existed, if so no invitation record was
created and the user was automatically
attached

InvitorPlayFabId String Identity of the user who created the


invitation

StudioPermissions [] Array of studio permissions which will


be granted to the user when
registering

TitlePermissions Object Dictionary of title id, title permissions


which will be granted to the user when
registering

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.
NAME TYPE DESC RIP T IO N

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
studio_user_removed
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a user is removed from a studio.

Properties
NAME TYPE DESC RIP T IO N

AuthenticationId String Authentication provider's ID for this


user

AuthenticationProvider AuthenticationProvider Authentication provider for the user

AuthenticationProviderId String Authentication provider entity id, if


needed by the provider

PlayFabId String PlayFab ID for this user

StudioPermissions [] Array of studio permissions that the


user had

TitlePermissions Object Dictionary of title id, title permissions


that the user had

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.
NAME TYPE DESC RIP T IO N

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
tenancy_connector_onboard
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a tenancy connector is onboarded.

Properties
NAME TYPE DESC RIP T IO N

EntityChain String The chain of ownership for this entity.

EntityLineage EntityLineage Entities that this entity is a child of.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.
NAME TYPE DESC RIP T IO N

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
title_aborted_task
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a task instance is aborted.

Properties
NAME TYPE DESC RIP T IO N

DeveloperId String

TaskInstanceId String ID of the aborted task instance

UserId String

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'
NAME TYPE DESC RIP T IO N

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
title_added_cloudscript
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when new CloudScript is uploaded to PlayFab.

Properties
NAME TYPE DESC RIP T IO N

DeveloperId String

Published Boolean Whether the CloudScript that was


uploaded is live.

Revision int32 Revision number of the CloudScript file


that was added.

ScriptNames [] Names of the individual script files


modified. Currently this is just
'CloudScript.js' but later we will
support multiple files.

UserId String

Version int32 Version number of the CloudScript file


that was added.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.
NAME TYPE DESC RIP T IO N

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
title_api_settings_changed
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when an API Features setting is changed for the title.

Properties
NAME TYPE DESC RIP T IO N

DeveloperId String

PreviousSettingsValues APISettings Settings values before the change.

SettingsValues APISettings Settings values after the change.

UserId String

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'
NAME TYPE DESC RIP T IO N

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
title_catalog_updated
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a catalog is changed.

Properties
NAME TYPE DESC RIP T IO N

CatalogVersion String Version of the catalog that was


updated.

Deleted Boolean Was the catalog deleted.

DeveloperId String

UserId String

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'
NAME TYPE DESC RIP T IO N

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
title_client_rate_limited_alert
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a single IP address generates too many API calls to PlayFab and is throttled.

Properties
NAME TYPE DESC RIP T IO N

AlertEventId String Unique identifier of the alert that


triggered this event.

AlertState AlertStates State of the alert. Values include


Triggered, Recovered, ReTriggered.

API String The PlayFab API that was called too


frequently.

ErrorCode String Error message that was returned to


the client.

GraphUrl String URL of an image graph of the counter


that triggered the alert.

Level AlertLevel Level of the alert. Values include Warn,


Alert, Critical.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.
NAME TYPE DESC RIP T IO N

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
title_completed_task
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a scheduled task has completed

Properties
NAME TYPE DESC RIP T IO N

AbortedAt DateTime Timestamp on when the task was


aborted. Null if task never was
aborted.

IsAborted Boolean Whether the task was aborted.

Result TaskInstanceStatus Result of the task run, whether it has


succeeded, failed or aborted.

Summary object Summary of the task run. Different


task types have different summary
structure.

TaskInstanceId String ID of the running instance of the task

TaskType String Type of the scheduled task

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.
NAME TYPE DESC RIP T IO N

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
title_created_task
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a task is created.

Properties
NAME TYPE DESC RIP T IO N

DeveloperId String

ScheduledTask NameIdentifier Identity of the scheduled task

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.
NAME TYPE DESC RIP T IO N

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
title_deleted
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a game title is deleted.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.
NAME TYPE DESC RIP T IO N

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
title_deleted_master_player
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a GDPR delete is finished.

Properties
NAME TYPE DESC RIP T IO N

MetaData String Identifying information for title entered


by developer.

PlayerId String Master Player ID who was deleted.

ReceiptId String Receipt ID of the delete that has been


finished.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'
NAME TYPE DESC RIP T IO N

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
title_deleted_task
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a task is deleted.

Properties
NAME TYPE DESC RIP T IO N

DeveloperId String

ScheduledTask NameIdentifier Identity of the scheduled task

UserId String

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'
NAME TYPE DESC RIP T IO N

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
title_exceeded_limit
5/24/2022 • 2 minutes to read • Edit Online

This event is triggererd when a title exceeds a service limit and receives an error.

Properties
NAME TYPE DESC RIP T IO N

Details Object Additional details about the exceeded


limit

LimitDisplayName String The display name of the limit that was


exceeded.

LimitId String The unique identifier of the limit that


was exceeded.

LimitValue double The limit value that was exceeded.

Unit MetricUnit The unit of the limit that was exceeded.

Value double The value that exceeded the limit.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.
NAME TYPE DESC RIP T IO N

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
title_game_build_added
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a new game build is uploaded for a game title.

Properties
NAME TYPE DESC RIP T IO N

BuildId String Unique identifier of the build that was


uploaded.

DeveloperId String

MaxGamesPerHost int32 The maximum number of game


sessions that can be run on a single
server.

MinFreeGameSlots int32 The minimum number of free slots to


maintain across all servers for this
build.

Regions Region This build is being deployed in these


regions and will shortly be available for
players to join.

UserId String

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be pre-pended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.
NAME TYPE DESC RIP T IO N

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
title_game_build_modified
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when any of the game build settings are modified.

Properties
NAME TYPE DESC RIP T IO N

BuildId String Unique identifier of the build that was


modified.

DeveloperId String

MaxGamesPerHost int32 The maximum number of game


sessions that can be run on a single
server.

MinFreeGameSlots int32 The minimum number of free slots to


maintain across all servers for this
build.

Regions Region List of regions where the build has


been deployed.

UserId String

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.
NAME TYPE DESC RIP T IO N

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
title_high_error_rate_alert
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a game title experiences a high rate of errors.

Properties
NAME TYPE DESC RIP T IO N

AlertEventId String Unique identifier of the alert that


triggered this event.

AlertState AlertStates State of the alert. Values include


Triggered, Recovered, ReTriggered.

API String The PlayFab API that is generating the


high rate of errors.

ErrorCode String Error message that was returned to


the client.

GraphUrl String URL of an image graph of the counter


that triggered the alert.

Level AlertLevel Level of the alert. Values include Warn,


Alert, Critical.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.
NAME TYPE DESC RIP T IO N

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
title_initiated_player_password_reset
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a title initiates the account recovery process for a player.

Properties
NAME TYPE DESC RIP T IO N

DeveloperId String

PasswordResetId String Unique identifier for the password


reset link. This cannot be used to
complete the reset.

PlayerId String Player's account ID.

PlayerRecoveryEmailAddress String Email address to which the account


recovery email was sent.

UserId String

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.


NAME TYPE DESC RIP T IO N

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
title_limit_changed
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a title changes a service limit.

Properties
NAME TYPE DESC RIP T IO N

LimitDisplayName String The display name of the limit that


changed.

LimitId String The unique identifier of the limit that


changed.

PreviousPriceUSD double The price of the limit level in US Dollars


before the change, if any.

PreviousValue double The limit value before the change, if


any.

PriceUSD double The price of the limit level in US


Dollars, if any.

TransactionId String The unique identifier of the limit


change transaction.

Unit MetricUnit The unit of the limit that changed.

Value double The limit value after the change, if any.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.
NAME TYPE DESC RIP T IO N

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
title_news_updated
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a title news is created or updated.

Properties
NAME TYPE DESC RIP T IO N

DateCreated DateTime When the title news was initially


created.

NewsId String Id of the news that is new or updated.

NewsTitle String The current title of the news that is


new or updated.

Status NewsStatus The current status of the news that is


new or updated.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.


NAME TYPE DESC RIP T IO N

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
title_permission_policy_changed
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when an update occurs to a a title's permission policies.

Properties
NAME TYPE DESC RIP T IO N

DeveloperId String

NewPolicy String The contents new policy.

PolicyName String The name of the policy that was


changed

UserId String

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'
NAME TYPE DESC RIP T IO N

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
title_profile_view_constraints_changed
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a profile view constraint is changed for the title.

Properties
NAME TYPE DESC RIP T IO N

DeveloperId String

PreviousProfileViewConstraints String Profile view constraints before the


change as a JSON string.

ProfileType String The profile type of the profile view


constraints.

ProfileViewConstraints String Profile view constraints after the


change as a JSON string.

UserId String

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.


NAME TYPE DESC RIP T IO N

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
title_published_cloudscript
5/24/2022 • 2 minutes to read • Edit Online

An inactive revision of CloudScript has been made into the active 'live' version.

Properties
NAME TYPE DESC RIP T IO N

DeveloperId String

Revision int32 Revision number of the CloudScript


that was activated.

UserId String

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'
NAME TYPE DESC RIP T IO N

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
title_queue_config_updated
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a queue config is changed.

Properties
NAME TYPE DESC RIP T IO N

Deleted Boolean Was the queue config deleted.

DeveloperId String

MatchQueueName String Name of the queue config that was


updated.

UserId String

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'
NAME TYPE DESC RIP T IO N

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
title_requested_limit_change
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a title requests a service limit change.

Properties
NAME TYPE DESC RIP T IO N

DeveloperId String

LevelName String The name of the requested limit level.

LimitDisplayName String The display name of the limit


requested to change.

LimitId String The unique identifier of the limit


requested to change.

PreviousLevelName String The name of the limit level at the time


of the requested change, if any.

PreviousPriceUSD double The price of the limit level in US Dollars


at the time of the requested change, if
any.

PreviousValue double The limit value at the time of the


requested change, if any.

PriceUSD double The price of the requested limit level in


US Dollars, if any.

TransactionId String The unique identifier of the requested


limit change transaction.

Unit MetricUnit The unit of the limit requested to


change.

UserId String

Value double The limit value of the requested


change, if any.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N


NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
title_saved_survey
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a game's survey is saved.

Properties
NAME TYPE DESC RIP T IO N

Genre String Title Genre

Monetization [] Array of Monetization methods used


by the Title

Platforms [] Array of Platforms used by the Title

PlayerModes [] Array of PlayerModes used by the Title

TitleName String Name of the Title

TitleWebsite String Website for the Title

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.


NAME TYPE DESC RIP T IO N

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
title_scheduled_cloudscript_executed
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a CloudScript function is run by a scheduled task.

Properties
NAME TYPE DESC RIP T IO N

CloudScriptExecutionResult ExecuteCloudScriptResult Result of the CloudScript function,


including an error information. Useful
for debugging.

FunctionName String Name of the CloudScript function that


was called.

ScheduledTask NameId Scheduled task that called the


CloudScript

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'
NAME TYPE DESC RIP T IO N

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
title_secret_key_changed
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a title adds or updates a Secret Key

Properties
NAME TYPE DESC RIP T IO N

Deleted Boolean Flag indicating if the key was deleted


by this operation. Either true or null.

DeveloperId String

Disabled Boolean Flag indicating if the key is disabled

ExpiryDate DateTime Optional UTC date time that the secret


key will expire at.

SecretKeyId String Id of the secret key affected.

SecretKeyName String Name of the secret key affected.

UserId String

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.
NAME TYPE DESC RIP T IO N

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
title_started_task
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a task is scheduled to run.

Properties
NAME TYPE DESC RIP T IO N

DeveloperId String

Parameter object Parameter of the scheduled task

ScheduledByUserId String ID of user who manually scheduled the


task, null if scheduled automatically

ScheduledTask NameIdentifier Identity of the scheduled task

TaskInstanceId String ID of the running instance of the task

TaskType String Type of the scheduled task

UserId String

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.
NAME TYPE DESC RIP T IO N

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
title_statistic_version_changed
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when the version of a statistic changes, causing its leaderboard to reset.

Properties
NAME TYPE DESC RIP T IO N

ScheduledResetInterval StatisticResetIntervalOption The interval on which the statistic


leaderboard was configured to reset, if
any.

ScheduledResetTime DateTime The time at which the statistic


leaderboard was configured to reset, if
any.

StatisticName String Unique name of the statistic.

StatisticVersion uint32 Version of the statistic, following the


update.

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.


NAME TYPE DESC RIP T IO N

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
title_store_updated
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a store is changed.

Properties
NAME TYPE DESC RIP T IO N

CatalogVersion String Catalog version that the updated store


belongs to.

Deleted Boolean Was the store deleted.

DeveloperId String

StoreId String ID of the updated store.

UserId String

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.


NAME TYPE DESC RIP T IO N

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
title_updated_task
5/24/2022 • 2 minutes to read • Edit Online

This event is triggered when a task is updated.

Properties
NAME TYPE DESC RIP T IO N

DeveloperId String

HasRenamed Boolean

ScheduledTask NameIdentifier Identity of the scheduled task

UserId String

Common Properties
All PlayStream events are formatted as JSON objects and share the following common properties:

NAME TYPE DESC RIP T IO N

CustomTags Object Key-Value pair storage. Any provider


of this event schema is allowed to send
additional values in this property.

EntityId String The identifier for the entity (title,


player, etc) to which this event applies.

EntityType String The type of entity (player, title, etc.) to


which this event applies. If PlayFab is
meant to take action on this entity,
then the EntityType must be either
'player', 'character', or 'title'. It is
required that any entity type that
PlayFab does not currently parse
should be prepended with a
namespace (like 'com.mygame.guild')
as PlayFab may begin to parse root
entities at any time.

EventId String PlayFab-assigned unique identifier for


this event.

EventName String The name of this event.

EventNamespace String The assigned namespacing for this


event. For example:
'com.myprogram.ads'
NAME TYPE DESC RIP T IO N

History PlayStreamEventHistory The history of events associated with


this event. This is set in cases where an
event has generated children events
via a trigger action.

Reserved object Reserved exclusively for PlayFab


internal use.

Source String The name of the source of this


PlayStream event; will be PlayFab if the
event originated from us.

SourceType SourceType The type of source of this event


(PlayFab partner, other backend, or
from the PlayFab API).

Timestamp DateTime The time (in UTC) associated with this


event.
API access policy
5/24/2022 • 3 minutes to read • Edit Online

The API Access Policy controls access to API resources. At times it is necessary for a title to allow or deny certain
APIs from the game client, for anti-cheat or other security purposes. You can control the access using Policy
Statements to specify a set of access rules that are applied in specific situations.
This topic discusses the use API permission policies to create the appropriate rules.

IMPORTANT
This guide discusses advanced techniques. If applied incorrectly, it is possible to completely disable client access to your
title using this feature.

Policy control and structure


Titles use the PlayFab Admin API calls to retrieve and update the access policies. The two specific calls that you
use to set the API access policy are GetPolicy and UpdatePolicy. For more information about the Admin API calls,
see PlayFab API Reference.
To use the Admin API you must provide the developer secret key associated with your title. The Developer key is
used to authorize your Title to make Admin API calls. For information about retrieving your secret key, see
Secret key management.
Each policy contains a list of statements, which act as rules for one or more PlayFab resources. PlayFab defines a
default set of policy statements that allows all policies. If you delete this set of policy statement with out
replacing it, your Title will not be able to call the Client APIs.
The default PlayFab policy statements:

"Statements": [
{
"Resource": "pfrn:api--*",
"Action": "*",
"Effect": "Allow",
"Principal": "*",
"Comment": "The default allow all policy"
}
]

Each set of Permission Statements consists of the following items as defined in Authentication - Update Policy:
Resource - A string that uniquely identifies one or more PlayFab resources.
To describe the API resource, use the convention shown below.
pfrn:api--/API-GROUP/API-CALL

Specify the Client API as the API-GROUP : Client , Server , or Admin .


Replace API-CALL with an API name such as ConfirmPurchase , LoginWithTwitch , or ReportPlayer .
A resource string supports wildcards. The following resource string matches any resource.
pfrn:api--*

Action - A string that describes an operation to perform on the resource. Use * to match any operation.
Effect - A string that specifies a rule definition. Use Allow or Deny to allow or deny operations over the
resource.
Principal - A string that uniquely identifies the class of the user. Use * to match any user.
Comment - A user-defined string that provides more information about the policy statement.
ApiConditions - An optional object that defines advanced rule conditions, for example - Encryption and
Signed Headers.
You can set strong security rules for your application by modifying your policy to use more detailed permission
statements that only allows access by the APIs you use in your application.
The following example shows how to restrict the DeleteCharacterFromUser call:

{
"Resource": "pfrn:api--/Server/DeleteCharacterFromUser",
"Action": "",
"Effect": "Deny",
"Principal": "",
"Comment": "Disable server character delete"
}

API access policy example


The following code sample shows basic operations with policies. The code performs the following actions:
Retrieves and logs the existing Policy .
Updates the policy.
Retrieves and logs the existing Policy again.
public void Start() {
PlayFabSettings.staticSettings.DeveloperSecretKey = "<insert key here>";
PlayFabSettings.TitleId = "< insert title id here >";
FetchApiPolicy(UpdateApiPolicy);
}

private void FetchApiPolicy(Action nextAction = null) {


PlayFabAdminAPI.GetPolicy(new GetPolicyRequest() {
PolicyName = "ApiPolicy"
}, result => {
Debug.Log(result.PolicyName);
foreach (var statement in result.Statements)
{
Debug.Log("Action: "+ statement.Action);
Debug.Log("Comment: "+ statement.Comment);
if(statement.ApiConditions != null)
Debug.Log("ApiCondition.HashSignatureOrEncryption: "+
statement.ApiConditions.HasSignatureOrEncryption);
Debug.Log("Effect: "+ statement.Effect);
Debug.Log("Principal: "+statement.Principal);
Debug.Log("Resource: "+ statement.Resource);
}

if (nextAction != null) nextAction();

},error=>Debug.LogError(error.GenerateErrorReport()));
}

private void UpdateApiPolicy() {


PlayFabAdminAPI.UpdatePolicy(new UpdatePolicyRequest() {
PolicyName = "ApiPolicy",
OverwritePolicy = false, // Append to existing policy. Set to True, to overwrite.
Statements = new List<PermissionStatement>() {
new PermissionStatement() {
Action = "*", // Statement effects Execute action
ApiConditions = new ApiCondition() {
HasSignatureOrEncryption = Conditionals.False // Require no RSA encrypted payload or
signed headers
},
Comment = "Do not allow clients to confirm purchase",
Resource = "pfrn:api--/Client/ConfirmPurchase", // Resource name
Effect = EffectType.Deny, // Do not allow,
Principal = "*"
}
}
}, result => {
FetchApiPolicy();
}, error => Debug.LogError(error.GenerateErrorReport()));
}

The image below shows an example of the output after the code is run the first time. As shown, the policy
consists of several Permission Statements.
Global API method error codes
5/24/2022 • 3 minutes to read • Edit Online

This tutorial lists the global error codes that apply to every PlayFab API method. The following information can
be used to decipher API errors.
Each API error contains the following fields:
Error - A human-readable code for the error.
ErrorCode - A numerical code for the error.

NOTE
This page lists the common error codes that you might encounter. If the error code you are looking for is not available on
this page, ask for additional information on the PlayFab forum.

Safe to retry codes


It is usually safe to retry requests that fail with these error codes, with an exponential delay back-off. These
errors typically mean that your client is making calls too quickly, but the request itself may be valid.
APIClientRequestRateLimitExceeded (1199) : Indicates too many calls in a short burst.
APIConcurrentRequestLimitExceeded (1342) : Indicates too many simultaneous calls.
ConcurrentEditError (1133) : Indicates too many simultaneous calls or very rapid sequential calls.
DataUpdateRateExceeded (1287) : Indicates too many simultaneous calls, or very rapid sequential calls.
DownstreamServiceUnavailable (1127) : Indicates that PlayFab or a third-party service might be having a
temporary issue.
InvalidAPIEndpoint (1131) : Indicates that the URL for this request is not valid for this title.
OverLimit (1214) : Indicates that an attempt to perform an operation will cause the service usage to go
over the limit as shown in the Game Manager limit pages. Evaluate the returned error details to
determine which limit would be exceeded.
ServiceUnavailable (1123): Indicates that PlayFab may be having a temporary issue or the client is
making too many API calls too quickly.

Never retry codes


If you get these error codes, you should never retry, because the request can never be completed under the
current circumstances without a bug-fix or setting change.
Most specific codes listed with an API method also fall into this category.
AccountBanned (1002):
The player account has been banned, all API methods will fail with this error.
AccountDeleted (1322) : The player account has been deleted, all API methods will fail with this error.
AccountNotFound (1001) : The player account does not exist, likely because you are not copying a
PlayFabId/TitlePlayerId correctly. This error will always occur if the identifier is not correct.
APIRequestsDisabledForTitle (1295) : All API requests have been disabled for this title, and it can no
longer be used.
InvalidContentType (1144): It should be impossible to get this if you're using one of our SDKs. If you're
making your own raw HTTPS calls to PlayFab API methods, your Content-Type header must be
application/json . No other formats are accepted.

InvalidParams (1000) : The API request object sent to PlayFab has invalid parameters and cannot be
executed.
InvalidRequest (1071) : The API request object sent to PlayFab is invalid and cannot be executed.
InvalidTitleId (1004) : The request provided a TitleId which does not match the title provided in the URL
of the method. In most SDKs, you should not specify a TitleId for login requests, as it is done for you. In
the admin API, explicit TitleIds are a Dev ->Test ->Live safety feature.
NotAuthenticated (1074) : The client has tried to call an API that requires SessionTicket authentication,
without logging in first.
NotAuthorized (1089) : Incorrect credentials, or otherwise bad inputs related to logging in.
NotAuthorizedByTitle (1191) : This method has been disabled by the API Policy, and cannot be called.
ProfileDoesNotExist (1298) : Attempted to access an entity (player, character, title, etc.), which does not
exist. Probably a typo, or you've got a bad input somewhere.
TitleDeleted (1347) : This title has been deleted from PlayFab, and can no longer be used.
UnknownError (1039) : This typically occurs if bad information is sent to a third-party add-on, and our
server experienced an unknown result or error while interacting with external systems. To resolve this,
experiment with your inputs, and try to determine if your inputs are invalid in some way. Otherwise,
report the error on the forums, with your titleId, the full request JSON (if possible), and the error output.
Postman is a useful tool for debugging this situation.

Other notable error codes


These codes only occur on specific API methods (listed on the documentation page for those methods), but if
you see them, there are important consequences of which you should be aware.
APIConcurrentRequestLimitExceeded (1342) : Your title is either hitting CloudScript too hard, or is trying to
force segment evaluation too frequently (or both). For the former, the two things to examine are:
1. How often your script calls utilize near-maximum time per call (or worse, time out).
2. How frequently you're calling CloudScript per player. Calls to get the list of players in a segment would
be the key thing to examine (a task targeting a segment also causes re-evaluation, but that should be
infrequent).
HTTP response status codes
5/24/2022 • 2 minutes to read • Edit Online

This article lists global HTTP response status codes and what they mean. It also includes extra description that
generally applies to all PlayFab APIs.
Use this page as a reference guide to troubleshoot issues related to HTTP web requests. For specific descriptions
that relate to a particular API, you have to go to the documentation page for that API.
If you're getting a status code that is not listed here, let us know on PlayFab forums and categorize your question
under API and SDK questions .

NOTE
Not every API can return all of the status codes listed below. There are APIs that only return some of the codes.

H T T P STAT US C O DE GEN ERA L DESC RIP T IO N

100 Continue: Returned on HEAD requests

200 OK: Returned for all successful requests. May indicate partial
success for bulk APIs.

201 Created: Request was successful and resource was created.

202 Accepted: Request was successful, processing will continue


asynchronously.

204 No Content: API successful, but there is no response to be


returned from the API.

400 Bad Request: Parameters in request where invalid or request


payload structure was invalid. Do not retry.

401 Unauthorized: Caller is not authorized to either call the


specific API or perform the action requested. Do not retry.

403 Forbidden: Caller is not allowed access. Do not retry.

404 Not Found: API does not exist. Do not retry.

408 Request Timeout: The request took too long to be sent to


the server. Okay to retry using exponential backoff pattern.

409 Conflict: A concurrency error occurred between two API calls.


Okay to retry using exponential backoff pattern.

413 Payload Too Large: The request is larger than the server is
allowed to handle. Do not retry. If unexpected, contact
support.
H T T P STAT US C O DE GEN ERA L DESC RIP T IO N

414 URI Too Long: The URI in the request is longer than the
server is allowed to handle. Do not retry.

429 Too Many Requests: API calls are being rate limited. Pause
and then retry request, check if API returned “Retry-After”
header or retryAfter in JSON response for delay needed.

500 Internal Server Error: An error occurred on the PlayFab


server. Okay to retry, contact support if problem persists.

501 Not Implemented: The API called has not been implemented
yet. Do not retry.

502 Bad Gateway: PlayFab API servers are not available to


process the request. Pause and then retry request using
exponential backoff pattern.

503 Service Unavailable: PlayFab API servers are not available to


process the request. Pause and then retry request using
exponential backoff pattern.

504 Gateway Timeout: PlayFab API servers are not available to


process the request. Pause and then retry request.

See also
PlayFab API reference documentation
SDKs overview
5/24/2022 • 2 minutes to read • Edit Online

This topic describes the different SDKs we have.


There are three types of SDKs to facilitate the use of PlayFab features and services in your title, on the platform
of your choice. Each type of SDK is available in different flavors to support your title development on popular
engines and platforms. They are typically wrappers around REST APIs.

PlayFab SDK
PlayFab SDK enables you to use a majority of our features, including LiveOps, economy, matchmaking, and data
analytics. For more information, see PlayFab SDKs.

PlayFab Party SDK


PlayFab Party SDKs provides networking and voice/text chat communication for games. For more information,
see Party SDKs.

PlayFab Multiplayer Game Server SDK


PlayFab Multiplayer Game Server SDKs (GSDKs) provide native C++, C#, and Java libraries to help you manage
your PlayFab Multiplayer Servers (MPS). For more information, see Multiplayer Game Server SDKs.

TIP
We strongly recommend that you use the latest versions of the SDKs. All SDK versions released in the past 6 months are
fully supported unless specified otherwise. For Unreal Engine and Unity plugins, we generally support the latest 2
versions. With each release of the SDKs, we support compatibility with newest partner platform versions. Please reach out
to developer support if you have any questions.

See also
PlayFab Party SDKs
PlayFab Party quickstart
PlayFab Multiplayer Game Server SDKs
PlayFab Multiplayer Server quickstart (API/PowerShell)
PlayFab Multiplayer Server quickstart (Game Manager)
Request access for secured SDKs and samples
5/24/2022 • 2 minutes to read • Edit Online

This topic provides information about how you can access SDKs and samples for Nintendo Switch ,
PlayStation 4 , PlayStation 5 , and Google Stadia .
Adhering to platform policies, we need to ensure that you're a registered developer before granting access, so a
few extra steps are required from you. For example, you need to be a registered Switch developer to get access
to Party SDKs and samples for Switch.

NOTE
For other platforms, operating systems, and frameworks, you don't have to request for access to start using Party SDKs
and samples.

If you're not yet a registered developer for the previously mentioned platforms and want to become one, go to
their developer page to learn more. To become a registered developer for Xbox and PC, go to ID@Xbox.

Switch and PlayStation


Switch, PS4, and PS5
1. Go to the Nintendo/Sony developer portal, and then find our page (categorized under Middleware).
2. Follow the instructions there. Use their site to send us a notification to let us know that you're a registered
developer.

Stadia
1. Email PlayFabSdkAccess@microsoft.com with your developer information.
2. After we've verified that you're a registered developer for Stadia, we'll grant you access.

Need help?
If you have more questions, post them on PlayFab forums or directly contact developer support for Nintendo,
Sony, Google, or Xbox.

See also
Party SDKs
Party samples
Getting started with Party
Azure Playfab Lobby and Matchmaking SDKs
5/24/2022 • 2 minutes to read • Edit Online

[!IMPORTANT] This feature is currently in public preview. It is provided to give you an early look at an
upcoming feature, and to allow you to provide feedback while it is still in development.

This article describes all the Azure PlayFab Lobby and Matchmaking SDKs that are currently available.
If you don't find what you need, let us know by writing a post on our forums.
Access to SDKs for Nintendo Switch, PlayStation 4, PlayStation 5, and Xbox (GDK) requires special approval and
adherence to platform policies.
If you're looking for the core PlayFab SDK that helps you implement most of our features, including LiveOps,
economy, matchmaking, and data analytics, see PlayFab SDKs.

[!Tip] Unsure if this is the SDK you need? See SDK overview - PlayFab SDK, Party SDK, Multiplayer Server
SDK.

By content type
SDK / L IB RA RY P L AT F O RM / O P ERAT IN G SY ST EM

C/C++ SDK PC(Win32), Nintendo Switch, PlayStation 4, PlayStation 5, PC


(GDK) and Xbox (GDK)

Unity SDK PC (Win32), PC (GDK) and Xbox (GDK), Nintendo Switch,


PlayStation 4, PlayStation 5

Unity Editor Extensions Unity game engine

Unreal SDK PC (GDK), Xbox (GDK), Steam, Nintendo Switch

See also
Quickstart for Unity
Quickstart for Unreal
Lobby overview
Getting started with Lobby
PlayFab Multiplayer C++ SDK release notes
5/24/2022 • 2 minutes to read • Edit Online

1.1.1
April 13, 2022
Bug fixes
Switch: Provides a new PAL header required to build against PlayFab Multiplayer.

1.1.0
March 4, 2022
API changes
PFMultiplayerGetErrorMessage's API signature has changed. Previously this function returned an HRESULT
and used an output paramter to return the error message string. Now the function returns the string directly.
New features
GDK: Added support for automatically handling suspend and resume on Xbox.
Bug fixes
Fixed a bug where using initial member data passed to PFMultiplayerJoinLobby would be ignored if the
player was rejoining a lobby.

1.0.0
November 23, 2021
PlayFab Multiplayer is now available in private preview. For an overview of Matchmaking and Lobby features,
check out:
PlayFab Lobby Overview
PlayFab Multiplayer Lobby Quickstart
PlayFab Matchmaking Overview
PlayFab Multiplayer Matchmaking Quickstart
Overview
5/24/2022 • 2 minutes to read • Edit Online

The PlayFab Online Subsystem (PF OSS) enables you to make use of Multiplayer features like Lobby,
Matchmaking, Party and Azure Cognitive Services in your Unreal Engine 4 (UE4) game. These features include
cross-talk, cross-play, and accessibility features like real-time text chat translation and voice transcription
services. It is currently designed for use when developing PC, Xbox, Steam and Nintendo Switch games. This
subsystem layer works seamlessly on top of the existing Epic provided base Online Subsystem (OSS) GDK.
PlayFab OSS compliments the base OSS by adding support for PlayFab Lobby, Matchmaking, Party networking
and Voice over Internet Protocol (VOIP).
PlayFab OSS works alongside the PlayFab SDK marketplace plugin, which provides other PlayFab functionalities
such as economy, leaderboards, and more. For more information, see PlayFab SDK on the UE4 Marketplace
(external site).

What is included in the Online Subsystem?


Create, join and search lobbies
Quick matchmaking
Invite friends to game lobby
Game networking
VOIP
Support for the following platforms:
Xbox Series X GDK
PC GDK
Xbox One GDK
PC Steam
Nintendo Switch
Support for cross-play & cross-talk across the above platforms
Azure Cognitive Services
Real-time text chat translation
Real-time voice chat transcription
Real-time voice chat transcription translation
Text-to-speech synthesis

Which versions of Unreal Engine are supported?


We officially support 4.27 and 4.26, however 4.27 is the recommended version. Crossplay between different
platforms does not work on 4.26, but it does on 4.27. If you are on an earlier version of Unreal Engine 4, the OSS
can be backported with minimal work. Refer to the Using older versions of Unreal Engine 4 page for more
details.
NOTE: If you are using a version of UE4 earlier than 4.25plus, you will have to rename all references to GDK to
Anvil using find & replace all.

Which versions of the Microsoft Game Development Kit (GDK) are


supported?
PC
Recommended: June 2021 GDK (2021.06)
Minimum: November 2020 GDK (2020.11)
When utilizing a GDK version earlier than 2020.11 on PC, reach out to your Microsoft
Representative for further guidance.
Xbox GDK:
Recommended: June 2021 GDK (2021.06)
Minimum: June 2021 GDK (2021.06)
XDK is supported on older version(1.07 and earlier) of the OSS, refer Using older version for further details.

Which version of the Nintendo Switch SDKs are supported?


Recommended: Refer to the UEBuild.cs file in the UnrealBuildTool folder for the Switch.

Pricing
VOIP and Game Networking functionality is free for users signed in with an Xbox Live account,
regardless of platform.
Cognitive services and other services may have a cost associated with them. For details, see Billing for PlayFab
Party or reach out to your Microsoft Representative.
QuickStart: PlayFab Online Subsystem (OSS)
5/24/2022 • 3 minutes to read • Edit Online

This quickstart guide helps you set up and use Multiplayer features such as Lobby, Matchmaking and Party for
Xbox, PC, and Nintendo Switch games built using Unreal Engine 4. For the full list of supported platforms and
versions in UE4, see Supported platforms.
After following the relevant steps below for your target platforms, you'll be ready to start using the OSS.
Authentication, networking, VOIP, grouping into lobbies, and matchmaking will be handled on your behalf with
no other changes required.

Download and install PlayFab Online Subsystem


Go to UE OSS PlayFab to download or clone PlayFab Online SubSystem source.

What you need


PlayFab Title ID: If you don't have a Title ID configured for PlayFab Party, see Enabling PlayFab Party.
GDK and PC
Specific platform PlayFab Multiplayer and Par ty libraries: These files are provided with the source in
Download and install PlayFab Online Subsystem. If you need updated Party library files, then see Obtaining
PlayFab Party libraries.
Private platforms
Nuget.exe Find the location of Nuget.exe on your machine and add it to the PATH environment variable.
Specific platform PlayFab Multiplayer and Par ty libraries: run SetUpPrivateOSS.ps1 located in the
OnlineSubsystemPlayFab folder. This script will pull the binaries and source code for the supported
private platforms. You must have access to our private repositories.

Initial setup
Copy the OnlineSubsystemPlayFab folder and its contents from to your UE4 directory under
Engine\Plugins\Online
Apply the following changes to the Plugins section of your ".uproject" file. This will add the
OnlineSubsystemPlayFab to your plugin list.
You may remove any platforms that you're not shipping on
{
"Name": "OnlineSubsystemPlayFab",
"Enabled": true,
"WhitelistPlatforms": [
"XboxOneGDK",
"WinGDK",
"XSX",
"Win64",
"Switch"
],
"SupportedTargetPlatforms": [
"XboxOneGDK",
"WinGDK",
"XSX",
"Win64",
"Switch"
]
}

Game Configuration
No matter which platform you're targeting, your game will need to configure certain PlayFab specific values
in your intended platform target's INI file (located at [yourGameDirectory]/Platforms/[yourPlatform]/Config).
Xbox Series X GDK: XSXEngine.ini
PC GDK: WinGDKEngine.ini
Xbox One GDK: XboxOneGDKEngine.ini
PC Steam: WindowsEngine.ini
Nintendo Switch SwitchEngine.ini
Replace the INI sections in the config if they already exist (for example, Engine.GameEngine) with the ones
below.
Ensure you replace all the <REPLACE ME> fields with your data:
[OnlineSubsystemPlayFab]
bEnabled=true
PlayFabTitleID=<REPLACE ME with your PlayFab title ID>
MaxDeviceCount=<REPLACE ME with your max player count (note: split screen is still 1 device). In the example
of an 8 player game, this would be 8.>
MaxDevicesPerUserCount=<REPLACE ME with your max player count per box (note: split screen is still 1 device)
In the example of an 8 player game, this would be 1.>
MaxEndpointsPerDeviceCount=<REPLACE ME with your max player count per box (note: split screen is still 1
device) In the example of an 8 player game, this would be 1.>
MaxUserCount=<REPLACE ME with your max player count (note: split screen is still 1 device) In the example
of an 8 player game, this would be 8.>
MaxUsersPerDeviceCount=<REPLACE ME with your max player count per box (note: split screen is still 1 device)
In the example of an 8 player game, this would be 1.>
DirectPeerConnectivityOptions=<REPLACE ME with your connectivity options, in the form of an array of
strings. The default case corresponds to the following:
+DirectPeerConnectivityOptions=AnyPlatformType
+DirectPeerConnectivityOptions=AnyEntityLoginProvider>

[/Script/OnlineSubsystemPlayFab.PlayFabNetDriver]
NetConnectionClassName="OnlineSubsystemPlayFab.PlayFabNetConnection"
ReplicationDriverClassName="<REPLACE ME with your existing replication driver class name>"
ConnectionTimeout=15.0
InitialConnectTimeout=30.0

[/Script/Engine.GameEngine]
!NetDriverDefinitions=ClearArray
+NetDriverDefinitions=
(DefName="GameNetDriver",DriverClassName="OnlineSubsystemPlayFab.PlayFabNetDriver",DriverClassNameFallback="
OnlineSubsystemUtils.IpNetDriver")

Platform Specific Considerations


With all that done, we're nearly finished. There are only a few key platform-specific parameters left that must be
set.
GDK
If you're developing games using GDK, define the platform services and, optionally, set your GDK sandbox:

[OnlineSubsystem]
DefaultPlatformService=PlayFab
NativePlatformService=GDK

[OnlineSubsystemPlayFab]
Sandbox=<Optional, REPLACE ME with the sandbox Id used for the title under development >

Steam
If you're developing games for Win64 with Steam, define your platform services:

[OnlineSubsystem]
DefaultPlatformService=PlayFab
NativePlatformService=Steam

Switch
See the ReadMe.md file that comes with the Switch PlayFab OSS for more details.
Cross-platform
Finally, if your game makes use PlayFab's cross-platform networking support, define which platforms you'll
permit to connect:
[/Script/OnlineSubsystemUtils.OnlineEngineInterfaceImpl]
!CompatibleUniqueNetIdTypes=ClearArray
+CompatibleUniqueNetIdTypes=STEAM
+CompatibleUniqueNetIdTypes=GDK
+CompatibleUniqueNetIdTypes=SWITCH

This completes the setup of OSS required to be used in your game. Good luck!
Obtaining PlayFab Party libraries
5/24/2022 • 2 minutes to read • Edit Online

You will require PlayFab Party headers, library and DLL in order to be able to utilize this subsystem. See below
for the options available to you.

Using the GDK


PlayFab Party is included with the GDK and the OSS will use this version by default when building.

Using the XDK


PlayFab Party headers, libraries, and DLLs are not included in the XDK. You must perform the steps outlined
below in the XDK: Bringing your own PlayFab Par ty librar y section to obtain the XDK version of PlayFab
Party.
This can be obtained by extracting the PlayFab Party NuGet package and PlayFab Party Xbox Live NuGet package

XDK: Bringing your own PlayFab Party library


Navigate to the OnlineSubsystemPlayFabParty directory (where OnlineSubsystemPlayFabParty.uplugin is
located)
Create a new Platforms folder
Create a new XDK folder inside the above folder
Create these three new folders inside the XDK folder:
Include
Lib
Redist
Copy the following files into the relevant folder:
Include: All Party & PartyXboxLive header files
Lib: Party.lib & PartyXboxLive.lib
Redist: Party.dll, PartyXboxLive.dll, Party.pdb and PartyXboxLive.pdb
XDK builds will now use this version of PlayFab Party.
Introduction to Cognitive Services
5/24/2022 • 2 minutes to read • Edit Online

The PlayFab Party Cognitive Services Interface includes functions that allow for the configuration and use of the
accessibility features provided by PlayFab Party.
These features include:
Real-time text chat translation
Real-time voice chat transcription
Real-time voice chat transcription translation
Text-to-speech synthesis

Pricing
Cognitive Services and other services beyond core VOIP and game networking functionality may have a cost
associated with them. Please visit the Billing for PlayFab Party page for more details or reach out to your
Microsoft Representative.

Using the Cognitive Services Interface


To use the Cognitive Services Interface in your game, add the following block of code to your game's Build.cs file.

if (Target.bGenerateProjectFiles || (Target.Type != TargetType.Game && Target.Type != TargetType.Client))


{
PublicDefinitions.Add("WITH_OSS_PLAYFAB_COGNITIVESERVICES=0");
}
else
{
PublicDefinitions.Add("WITH_OSS_PLAYFAB_COGNITIVESERVICES=1");

PublicDependencyModuleNames.Add("OnlineSubsystemPlayFab");
PrivateDependencyModuleNames.Add("HTTP");
}

Additionally, you can wrap any game code with #if WITH_OSS_PL AYFAB_COGNITIVESERVICES to prevent
compilation errors on platforms that do not use Cognitive Services.

SetTextChatTranslationOptions
SetTextChatTranslationOptions allows chat translation to be toggled on or off.

SetVoiceChatTranscriptionOptions
SetVoiceChatTranscriptionOptions is required for enabling and configuring voice transcription.
bTranscribeSelf - Transcriptions of the local chat control will be generated and provided to the same local
chat control
bTranscribeOtherChatControlsWithMatchingLanguages - Transcriptions of other chat controls with
the same language as the local chat control will be generated and provided to the local chat control
bTranscribeOtherChatControlsWithNonMatchingLanguages - Transcriptions of other chat controls
with languages that are different from the local chat control's language will be generated and provided to the
local chat control
bTranslateToLocalLanguage - Transcriptions will be translated to the local chat control's language

SetTextToSpeechOptions
SetTextToSpeechOptions is required for enabling and configuring text to speech.
ETextToSpeechType::Narration - Render audio to the local chat control's audio output
ETextToSpeechType::VoiceChat - Render audio to chat controls which the local chat control is configured
to send audio to

SendTextAsVoice
Generates text to speech audio that is sent to all other clients connected to the PlayFab Party network. Text as
Voice must be enabled via a call to SetTextToSpeechOptions before calling SendTextAsVoice

SendChatText
Sends chat text string to all other clients connected to the PlayFab Party network.
Using older versions of Unreal Engine 4
5/24/2022 • 2 minutes to read • Edit Online

While not officially supported by the PlayFab Online Subsystem (OSS), it is entirely possible to use it on older
versions of Unreal Engine 4. Core networking functionality will migrate back to earlier versions of Unreal Engine
4 with minor tweaks to interface function names & signatures, with certain instances renamed or removed to
match older versions of the Unreal Engine 4 OSS interface.

XDK support on version 1.07 and earlier


Apply the changes below to the Game (not Engine) INI file 'XboxOneEngine.ini'
Replace the INI sections if they already exist (e.g. Engine.GameEngine)
Ensure you replace all the <REPLACE ME> fields with your data.

[OnlineSubsystem]
DefaultPlatformService=PlayFab
NativePlatformService=Live

[OnlineSubsystemPlayFab]
bEnabled=true
PlayFabTitleID=<REPLACE ME with your PlayFab title ID>
MaxDeviceCount=<REPLACE ME with your max player count (note: split screen is still 1 device). In the example
of an 8 player game, this would be 8.>
MaxDevicesPerUserCount=<REPLACE ME with your max player count per box (note: split screen is still 1 device)
In the example of an 8 player game, this would be 1.>
MaxEndpointsPerDeviceCount=<REPLACE ME with your max player count per box (note: split screen is still 1
device) In the example of an 8 player game, this would be 1.>
MaxUserCount=<REPLACE ME with your max player count (note: split screen is still 1 device) In the example
of an 8 player game, this would be 8.>
MaxUsersPerDeviceCount=<REPLACE ME with your max player count per box (note: split screen is still 1 device)
In the example of an 8 player game, this would be 1.>

[/Script/OnlineSubsystemPlayFab.PlayFabNetDriver]
NetConnectionClassName="OnlineSubsystemPlayFab.PlayFabNetConnection"
ReplicationDriverClassName="<REPLACE ME with your existing replication driver class name>"
ConnectionTimeout=15.0
InitialConnectTimeout=30.0

[/Script/Engine.GameEngine]
!NetDriverDefinitions=ClearArray
+NetDriverDefinitions=
(DefName="GameNetDriver",DriverClassName="OnlineSubsystemPlayFab.PlayFabNetDriver",DriverClassNameFallback="
OnlineSubsystemUtils.IpNetDriver")

Enabling cross-generational play between XDK and GDK


The default game implementation in Unreal Engine 4 validates that an incoming remote Net ID is of the same
subsystem type as the local instance, as such cross-play between XDK and GDK will have different types and
requires you to make one of the following changes:
Override the function within your GameMode and implement a PreLogin function which doesn’t require this
check or pass a nullptr to the base function for NetID, skipping the check.
You may have already this class overridden
Edit the base function AGameMode::PreLogin to remove the OSS type check (bUniqueIdCheckOk )
PlayFab Unreal Engine 4 OnlineSubsystem release
notes
5/24/2022 • 2 minutes to read • Edit Online

Refer to QuickStart: PlayFab Online Subsystem (OSS) for download and install instructions.

2.0.0
UE4 engine OSS PlayFab is updated to use Multiplayer features offered by Azure PlayFab such as Lobby,
Matchmaking along with PlayFab Party. This replaces the Xbox provided MPSD with Azure PlayFab Lobby and
XBL Smart match with Azure Matchmaking service.
XDK is not longer supported for this version of the OSS

1.0.7
UE4 Engine version 4.26 is the recommnded version to use with this version of OnlineSubsystemPlayfab.
Notes:
Rename OnlineSubsystemPlayFabParty to OnlineSubsystemPlayfab.
Getting started for Multiplayer Unity SDK
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

To get started, see the following topics.


Multiplayer Unity plugin overview
Specific Unity set up instructions.

See also
Getting started with Lobby
Lobby Client SDK reference
Getting started with Matchmaking
Matchmaking Client SDK reference
Multiplayer SDKs
PlayFab Multiplayer Unity plugin overview
5/24/2022 • 4 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

The PlayFab Multiplayer Unity SDK plugin is a Unity C# wrapper on top of a native PlayFabMultiplayer C++
library created for the convenience of Unity game developers.
It enables you to make use of PlayFab Multiplayer services in your Unity game. Currently, this includes Lobby
and Matchmaking. It is designed for developing games on multiple platforms.
PlayFab Multiplayer Unity plugin works alongside the PlayFab "core" Unity SDK. The PlayFab "core" Unity SDK
provides other PlayFab functionalities such as economy, leaderboards, and more. For more information, see
PlayFab Unity SDK and PlayFab Unity SDK documentation.
PlayFab Multiplayer Unity plugin is available for download as a Unity Asset package.

What API features are provided by PlayFab Multiplayer Unity plugin?


Lobby
Matchmaking
Support for the following platforms:
GDK:
Xbox Series X|S
Xbox One
PC
Windows
Support for cross-play across the above platforms

What is included in PlayFab Multiplayer Unity plugin?


The top-level Multiplayer API written in Unity C# provided by PlayFabMultiplayer class and a prefab for
integration of user's Unity game with PlayFabMultiplayer library
C# interop layer providing managed-code interface to the underlying native (C++) Multiplayer library API. It
is used by the top-level C# API.
Underlying native (C++) PlayFabMultiplayer binaries for each supported platform:
Multiplayer DLL libraries for GDK
Multiplayer DLL libraries for Windows
PlayFab "core" Unity SDK plugin (can be updated independently if needed)

PlayFab Multiplayer Unity plugin versions and compatibility between


platforms
PlayFab Multiplayer Unity plugin will be published and available for download at several distribution points (Git
repos), depending on the platform. Access to some distribution points is restricted. You need to send a request
to your Microsoft Representative and may include additional steps.
In order to provide a better guidance on compatibility between versions downloaded from different distribution
points, and reflect a reference to a specific version of the underlying native library, PlayFab Multiplayer Unity
plugin follows a custom versioning scheme.
PlayFab Multiplayer Unity plugin versioning scheme

X.X.X.Y-(distribution-point-indicator).Z

For example, 1.2.0.3-gdk.0 (a version downloaded from the GDK repo with restricted access) or 1.2.0.3-ps5.0
(a version with Multiplayer binaries only for PS5, downloaded from the PS5 repo with restricted access).
Version components:
X.X.X - the lowest version of the underlying PlayFabMultiplayer library across all supported platforms. This
is used for general reference consistency with a version of the underlying C++ library. In the example above,
the version of an included PlayFabMultiplayer library for each platform is 1.2.0 or higher.
Y - an incremental index of any modifications in the Multiplayer Unity C# layer, for any given X.X.X part of
the version.
(distribution-point-indicator) - a mnemonic code for tracking which distribution point a particular PlayFab
Multiplayer Unity plugin package was downloaded from. It differs by distribution point, for example, gdk
(Microsoft Azure DevOps repo with restricted access for GDK developers), ps5 (Microsoft Azure DevOps
repo with restricted access for PS5 developers), etc.
Z - an incremental index of any modifications unique to the distribution point (for example, Multiplayer
binaries updated/patched for a specific platform only).
A higher number in any version component means a newer version, by significance from left to right.
Compatibility between versions from different distribution points
Regardless of a distribution point a PlayFab Multiplayer Unity plugin is downloaded from, it is guaranteed to be
fully compatible with a PlayFab Multiplayer Unity plugin downloaded from any other distribution point, if the
first four numbers ( X.X.X.Y ) of their version are the same . Compatible versions from different
distribution points can be imported into user's Unity project in any order without a risk of overwriting/breaking
one another, as their shared code should be identical. Though each of them may have some additional (not
shared) files, specific to a particular platform, which shouldn't overlap.
For example, you can import all the following versions of PlayFab Multiplayer Unity plugin in your Unity project,
in any sequential order, if you are targeting GDK, PS5 and Switch:
1.2.0.3-gdk.0 (imports Multiplayer binaries for GDK, among other files)
1.2.0.3-ps5.0 (imports Multiplayer binaries for PS5, among other files)
1.2.0.3-sw.0 (imports Multiplayer binaries for Switch, among other files)

The shared (cross-platform) Unity C# code included in each of these plugins will be the same.

Which versions of Unity are supported?


We strive to support all recent versions of Unity starting with Unity 2017, however your choice may be limited
by availability of a Unity development add-on for each particular platform, see corresponding Unity
documentation. That, in turn, may also limit your choice of the platform SDK.
In general, we test PlayFab Multiplayer Unity plugin with one of the most recent versions of Unity development
add-ons available for each platform. We encourage you to report any build or runtime issues with any new
version of Unity Editor, Unity add-on, or a platform SDK.
Quickstart: PlayFab Multiplayer Unity plugin
5/24/2022 • 8 minutes to read • Edit Online

IMPORTANT
This feature is currently in public preview. It is provided to give you an early look at an upcoming feature, and to allow you
to provide feedback while it is still in development.

Get started with the PlayFab Multiplayer Unity plugin. Follow steps below to install the package and try out
example code for a basic task.
This quickstart helps you make your first API calls using the PlayFab Multiplayer SDK for Unity. Before
continuing, make sure you have completed Getting started for developers and Quickstart: PlayFab Client library
for C# in Unity, which ensures you have a PlayFab account and are familiar with logging into PlayFab from your
game and the PlayFab Game Manager.

NOTE
If you intend to use this plugin to develop games based on the Microsoft Game Development Kit (GDK) you need to
acquire and install the GDK separately. Please also see details about Unity add-on for Game Core on Xbox consoles.

Requirements
A PlayFab developer account.
An installed copy of the Unity Editor. To install Unity for personal use via Unity Hub, or Unity+ for
professional use, see Download Unity. Check on Unity support in documentation of your specific
platform if needed. The minimum supported Unity version is Unity 2017 LTS.
A Unity Project – this can be any of the following:
A brand new project: For more information, see Starting Unity for the first time.
A guided tutorial project. For more information, see Getting Started with Unity.
An existing project.
The PlayFab "core" Unity3D SDK (also included in Multiplayer Unity plugin). For information about
installing the Unity3D SDK, see the "Download and install PlayFab SDK" section of Quickstart: PlayFab
Client library for C# in Unity.

Download and install the PlayFab Multiplayer Unity plugin


Following the steps to download and install the PlayFab Multiplayer Unity plugin.
1. Download the PlayFab Multiplayer Unity Plugin Asset Package (use a distribution point depending on your
platform).
2. Impor tant! Please see information in README file published with plugin. It is tailored to each particular
version and may include important instructions specific to your platform.
3. Open your Unity Project.
4. Navigate to the location where you saved the .unitypackage and double-click it to open the import dialog.
5. To import the PlayFab Multiplayer Unity Plugin into your project, select Impor t .
Note: you may need to install a newer version of PlayFab "core" Unity SDK if necessary.

Set up your scene


This part of the guide shows you how to add the PlayfabMultiplayerEventProcessor to your scene to enable you
to call PlayFab Multiplayer APIs from Unity.
Before you can use Multiplayer API, you must have a PlayFab player logged in . For information about
logging in a player, see Making your first API call in Quickstart: PlayFab Client library for C# in Unity.
1. In the Unity editor, in the Project window, navigate to Assets > PlayFabMultiplayerSDK > Prefabs .
2. From the Prefabs folder, drag and drop the PlayfabMultiplayerEventProcessor into your scene in the
Hierachy window.
3. Create an empty Game Object in your scene called "HelloMultiplayerLogic".
4. Select the HelloMultiplayerLogic Game Object to open the Inspector .
5. Select Add Component .
6. Type "HelloMultiplayerLogic" and press enter to show the new script menu.
7. Press enter again to create the new script, HelloMultiplayerLogic.cs.
8. Find the script in the Project window and double-click it to edit the script.
9. Add the following using statement to your script:

using PlayFab;
using PlayFab.Multiplayer;
using PlayFab.ClientModels;

10. Add the following code in the Start method to log into PlayFab.

// Log into playfab


var request = new LoginWithCustomIDRequest { CustomId = UnityEngine.Random.value.ToString(),
CreateAccount = true };
PlayFabClientAPI.LoginWithCustomID(request, OnLoginSuccess, OnLoginFailure);

11. Add the following methods to the class.

private void OnLoginSuccess(LoginResult result)


{
}

private void OnLoginFailure(PlayFabError error)


{
}
NOTE
You might receive the following errors:

Error CS0227 Unsafe code may only appear if compiling with /unsafe
The plugin requires unsafe code because it interops with a native DLL.

Mismatch between the processor architecture of the project being built "MSIL" and the processor
architecture of the reference "XGamingRuntime", "AMD64".

The Microsoft GDK and Windows only support x64.


To resolve these issues:
1. In the Unity Editor, select File > Build Settings.
2. Select your platform. Then from the Architecture dropdown, select either x86_64 or x64.
3. Select Player Settings.
4. In the right pane, select Other Setting.
5. Find the Allow unsafe Code setting and select it.
6. Close the Build Settings and Project Settings windows.

Create and Join a lobby


This part of the guide shows you how to Create and Join a lobby.
1. Open the HelloMultiplayerLogic.cs script. In the OnLoginSuccess method, add the following code to create
and join a lobby:

string entityId = ...; // PlayFab user's entity Id


string entityType = ...; // PlayFab user's entity type

PlayFabMultiplayer.OnLobbyCreateAndJoinCompleted +=
this.PlayFabMultiplayer_OnLobbyCreateAndJoinCompleted;
PlayFabMultiplayer.OnLobbyDisconnected += this.PlayFabMultiplayer_OnLobbyDisconnected;

var createConfig = new LobbyCreateConfiguration()


{
MaxMemberCount = 10,
OwnerMigrationPolicy = LobbyOwnerMigrationPolicy.Automatic,
AccessPolicy = LobbyAccessPolicy.Public
};

createConfig.LobbyProperties["Prop1"] = "Value1";
createConfig.LobbyProperties["Prop2"] = "Value2";

var joinConfig = new LobbyJoinConfiguration();


joinConfig.MemberProperties["MemberProp1"] = "MemberValue1";
joinConfig.MemberProperties["MemberProp2"] = "MemberValue2";

PlayFabMultiplayer.CreateAndJoinLobby(
new PFEntityKey(
entityId,
entityType),
createConfig,
joinConfig);

2. To define the OnLobbyCreateAndJoinCompleted event handler, add the following code to the class:
private void PlayFabMultiplayer_OnLobbyCreateAndJoinCompleted(Lobby lobby, int result)
{
if (LobbyError.SUCCEEDED(result))
{
// Lobby was successfully created
Debug.Log(lobby.ConnectionString);
}
else
{
// Error creating a lobby
Debug.Log("Error creating a lobby");
}
}

3. To define the OnLobbyDisconnected event handler, add the following code to the class:

private void PlayFabMultiplayer_OnLobbyDisconnected(Lobby lobby)


{
// Disconnected from lobby
Debug.Log("Disconnected from lobby!");
}

4. Save and click Play in the Unity Editor. The lobby connection string displays in the Console window.

Join a lobby
This part of the guide shows you how to join an existing lobby that another client created.
1. Open the HelloMultiplayerLogic.cs script. In the OnLoginSuccess method, add the following code to Join a
lobby:

PFEntityKey entityKey = ...; // PlayFab user's entity key

string connectionString = "<your lobby connection string>";

PlayFabMultiplayer.JoinLobby(
entityKey,
connectionString,
null);

2. To define an event that fires when your local client joins the lobby, add the following code to the
OnLoginSuccess method:

PlayFabMultiplayer.OnLobbyJoinCompleted += this.PlayFabMultiplayer_OnLobbyJoinCompleted;

3. To define the OnLobbyJoinCompleted event handler, add the following code to the class:
private void PlayFabMultiplayer_OnLobbyJoinCompleted(Lobby lobby, PFEntityKey newMember, int reason)
{
if (LobbyError.SUCCEEDED(reason))
{
// Successfully joined a lobby
Debug.Log("Joined a lobby");
}
else
{
// Error joining a lobby
Debug.Log("Error joining a lobby");
}
}

4. Save and select Play in the Unity Editor. The string "Joined a lobby" displays in the Console window.

Find lobbies
This part of the guide shows you how to find existing lobbies that other clients created.
1. Open the HelloMultiplayerLogic.cs script. In the OnLoginSuccess method, add the following code to find
lobbies:

PFEntityKey entityKey = ...; // PlayFab user's entity key

LobbySearchConfiguration config = new LobbySearchConfiguration();


PlayFabMultiplayer.FindLobbies(entityKey, config);

2. To define an event that fires when your local client finds lobbies, add the following code to the
OnLoginSuccess method:

PlayFabMultiplayer.OnLobbyFindLobbiesCompleted +=
this.PlayFabMultiplayer_OnLobbyFindLobbiesCompleted;

3. To define the OnLobbyFindLobbiesCompleted event handler, add the following code to the class:

private void PlayFabMultiplayer_OnLobbyFindLobbiesCompleted(


IList<LobbySearchResult> searchResults,
PFEntityKey newMember,
int reason)
{
if (LobbyError.SUCCEEDED(reason))
{
// Successfully found lobbies
Debug.Log("Found lobbies");

// Iterate through lobby search results


foreach (LobbySearchResult result in searchResults)
{
// Examine a search result
}
}
else
{
// Error finding lobbies
Debug.Log("Error finding lobbies");
}
}
4. Save and select Play in the Unity Editor. The string "Found lobbies" displays in the Console window.

Create a matchmaking ticket


This part of the guide shows you how to Create a matchmaking ticket. Please run it in conjunction with scenario
"Join a matchmaking ticket" on another client below.
1. Open the HelloMultiplayerLogic.cs script. In the OnLoginSuccess method, add the following code to create
a matchmaking ticket:

PFEntityKey entityKey = ...; // PlayFab user's entity key


PFEntityKey remoteEntityKey = ...; // another PlayFab user's entity key
string remoteUserAttributesJson = ...; // JSON string with another PlayFab user's attributes for
matchmaking

PlayFabMultiplayer.OnMatchmakingTicketCompleted += PlayFabMultiplayer_OnMatchmakingTicketCompleted;
PlayFabMultiplayer.OnMatchmakingTicketStatusChanged +=
PlayFabMultiplayer_OnMatchmakingTicketStatusChanged;

List<MatchUser> localUsers = new List<MatchUser>();


localUsers.Add(new MatchUser(entityKey, remoteUserAttributesJson));

List<PFEntityKey> membersToMatchWith = new List<PFEntityKey>();


membersToMatchWith.Add(remoteEntityKey);

PlayFabMultiplayer.CreateMatchmakingTicket(
localUsers,
"QuickMatchQueueName",
membersToMatchWith);

2. To define the OnMatchmakingTicketStatusChanged event handler, add the following code to the class:

private void PlayFabMultiplayer_OnMatchmakingTicketStatusChanged(MatchmakingTicket ticket)


{
// Store and print matchmaking ticket
Debug.Log(ticket.TicketId);

// Share matchmaking ticket with other clients taking part in matchmaking

// Examine ticket
}

3. To define the OnMatchmakingTicketCompleted event handler, add the following code to the class:

private void PlayFabMultiplayer_OnMatchmakingTicketCompleted(MatchmakingTicket ticket, int result)


{
if (LobbyError.SUCCEEDED(result))
{
// Successfully completed matchmaking ticket
Debug.Log("Completed matchmaking ticket");

// Examine matchmaking details


MatchmakingMatchDetails details = ticket.GetMatchDetails();
}
else
{
// Error completing a matchmaking ticket
Debug.Log("Error completing a matchmaking ticket");
}
}
4. Save and click Play in the Unity Editor. The string "Completed matchmaking ticket" displays in the Console
window upon successful matchmaking.

Join a matchmaking ticket


This part of the guide shows you how to join an existing matchmaking ticket that another client created. Please
run it in conjunction with scenario "Create a matchmaking ticket" on another client above.
1. Open the HelloMultiplayerLogic.cs script. In the OnLoginSuccess method, add the following code to join a
matchmaking ticket:

PFEntityKey entityKey = ...; // PlayFab user's entity key


string ticketId = ...; // Matchmaking ticket obtained from the client that created the ticket

PlayFabMultiplayer.OnMatchmakingTicketCompleted += PlayFabMultiplayer_OnMatchmakingTicketCompleted;

// Create JSON string with PlayFab user's attributes for matchmaking. This will need to be shared
with other clients taking part in matchmaking
string uniqueId = System.Guid.NewGuid().ToString();
string userAttributesJson = "{\"MatchIdentifier\": \"" + uniqueId + "\"}";

PlayFabMultiplayer.JoinMatchmakingTicketFromId(
new MatchUser(entityKey, userAttributesJson),
ticketId,
"QuickMatchQueueName",
new List<PFEntityKey>());

2. To define the OnMatchmakingTicketCompleted event handler, add the following code to the class:

private void PlayFabMultiplayer_OnMatchmakingTicketCompleted(MatchmakingTicket ticket, int result)


{
if (LobbyError.SUCCEEDED(result))
{
// Successfully completed matchmaking ticket
Debug.Log("Completed matchmaking ticket");

// Examine matchmaking details


MatchmakingMatchDetails details = ticket.GetMatchDetails();
}
else
{
// Error completing a matchmaking ticket
Debug.Log("Error completing a matchmaking ticket");
}
}

3. Save and select Play in the Unity Editor. The string "Completed matchmaking ticket" displays in the
Console window upon successful matchmaking.
Azure Playfab Multiplayer Game Server SDKs
5/24/2022 • 2 minutes to read • Edit Online

This topic lists the different flavors of Azure PlayFab Multiplayer Game Server SDKs (GSDKs) we have today.

Download links
Note that these SDKs are for the servers.
Game Server SDK GitHub repo for all libraries
Unity Game Server SDK (GSDK)
C++ Game Server SDK (GSDK) for Windows servers via NuGet
C# Game Server SDK (GSDK) for Windows servers via NuGet
Java Game Server SDK (GSDK) for Windows and Linux servers via Maven

TIP
Unsure if this is the SDK you need? See SDKs overview - PlayFab SDK, Party SDK, Multiplayer Game Server SDK.

See also
SDKs overview
Azure Playfab Party SDKs
5/24/2022 • 2 minutes to read • Edit Online

This topic describes all the Azure PlayFab Party SDKs that are currently available.
If you don't find what you need, let us know by writing a post on our forums.
Access to SDKs for Nintendo Switch, PlayStation 4, PlayStation 5, Google Stadia, PC (GDK), and Xbox (GDK)
requires special approval and adherence to platform policies. For more information, see Request access for SDKs
and samples.
If you're looking for the core PlayFab SDK that helps you implement a majority of our features, including
LiveOps, economy, matchmaking, and data analytics, see PlayFab SDKs.

TIP
Unsure if this is the SDK you need? See SDK overview - PlayFab SDK, Party SDK, Multiplayer Server SDK.

By content type
SDK / L IB RA RY P L AT F O RM / O P ERAT IN G SY ST EM

C/C++ SDK Android, iOS, Windows 10, Windows 8.1, Stadia, Switch,
PlayStation®4, PlayStation®5, PC (GDK) and Xbox (GDK)
(Use the version that's included in the GDK.)

Unity SDK Android, iOS, Windows 10, Windows 8.1, PlayStation 4,


PlayStation 5, Switch, PC (GDK) and Xbox (GDK) (under
Add-ins )

Unity Editor Extensions Unity game engine

Unreal SDK PC (GDK) and Xbox (GDK) (under Add-ins )

Xbox Live Helper Library Windows 10, Windows 8.1, Windows 7, PC (GDK) and Xbox
(GDK) (Use the version that's included in the GDK.)

By platform/operating system
P L AT F O RM / O P ERAT IN G SY ST EM SDK / L IB RA RY

Android C/C++, C/C++ NuGet package, Unity

iOS C/C++, Unity

Stadia C/C++, C/C++ NuGet package

Switch C/C++, Unity, C/C++ and Unity NuGet packages


P L AT F O RM / O P ERAT IN G SY ST EM SDK / L IB RA RY

PlayStation 4 C/C++, Unity, C/C++ and Unity NuGet packages

PlayStation 5 C/C++, Unity, C/C++ and Unity NuGet packages

Xbox (XDK) C/C++, Xbox Live Helper Library

PC (GDK) and Xbox (GDK) Unity, Unreal (under Add-ins ), C/C++ SDK, Xbox Live
Helper Library (Use the version that's included in the GDK.)

Windows 10, Windows 8.1 C/C++, Xbox Live Helper Library

Windows 7 C/C++, Xbox Live Helper Library

See also
Party samples
Quickstart for Android
Quickstart for iOS
Quickstart for Unity
Quickstart for Unreal
Party overview
Getting started with Party
Android getting started
5/24/2022 • 4 minutes to read • Edit Online

This document lists the basic prerequisites and requirements necessary to integrate PlayFab Party into your
Android applications. Once you've set up your system according to this document, please have a look at the
Quickstart for PlayFab Party for getting set up with the building blocks of PlayFab Party.

Prerequisites
Before you start this tutorial, please ensure that the following prerequisites have been met:
1. You created a PlayFab developer account.
2. You created a PlayFab Title and your title has been allow-listed for PlayFab Party.
3. You have Android Studio version 3.2 or higher installed.
4. Your app targets Android 4.4 (Kitkat) or higher.
5. You have the Android NDK 18.1.5063045 or higher installed.
6. You have access to the PlayFab Party platforms repository
7. You have created an android signing cert and signed your app for deployment using the cert config.

Including the required libraries and header files


You'll need to include the following header files from the PlayFab Party distribution repository.
LIB Files
1. libParty.a
2. libcrypto.a
3. libssl.a

NOTE
The SSL libraries are built from Open SSL Version 1.1.1b-dev. Please use an openSSL version that is 1.1.1b-dev or higher.

Header Includes
Party Headers

NOTE
In addition to the lib files and headers above, you'll also need the libs and headers for PlayFab SDK and any other
platform-specific dependencies your app needs. Please take a look at the project file organization for the Android sample
for more info.

Steps to get PlayFab Party working on Android


Since the core Party library is written using C++, we'll need to make a simple JNI wrapper class to access the
Party lib functionality. At a high level, you'll want a class that has access to Party API methods to create a
network, connect to a network, and send messages across a network. We've achieved this in our demo app via
the NetworkManager Java class.

import android.util.Log;

public class NetworkManager {


static {
System.loadLibrary("partysample");
}

private MessageManager messageManager;

private static NetworkManager networkManager;

private NetworkManager() {
}

public static NetworkManager getInstance() {


if (networkManager == null) {
networkManager = new NetworkManager();
}
return networkManager;
}

public native boolean initialize(String name);

public native boolean createAndConnectToNetwork(String type, String languageCode);

public native boolean joinNetwork(String networkId);

public native void leaveNetwork();

public native void sendTextMessage(String message, boolean isTTS);

public native void doWork();

public native void getPlayerState();

public native void setLanguage(int idx);

public native void setPlayFabTitleID(String titleID);

public void onNetworkCreated(String network) {


Log.d(getClass().getSimpleName(), "onNetworkCreated: " + network);
getMessageManager().sendNetworkCreatedMessage(network);
getMessageManager().sendErrorMessage("Connected to network: " + network);
}

public void onMessageReceived(String sender, String message) {


Log.d(getClass().getSimpleName(), "onMessageReceived: " + sender + ": " + message);
getMessageManager().sendTextMsgReceivedMessage(sender, message, false);
}

public void onTranscriptMessageReceived(String sender, String message) {


Log.d(getClass().getSimpleName(), "onTranscriptMessageReceived: " + sender + ": " + message);
getMessageManager().sendTextMsgReceivedMessage(sender, message, true);
}

public void onPlayerJoined(String playerId, String name) {


Log.d(getClass().getSimpleName(), "onPlayerJoined: " + playerId + ": " + name);
getMessageManager().sendPlayerJoinMessage(playerId, name);
}

public void onPlayerLeft(String playerId) {


Log.d(getClass().getSimpleName(), "onPlayerLeft: " + playerId);
getMessageManager().sendPlayerLeftMessage(playerId);
}
}

public void toastMessage(String message) {


getMessageManager().toastMessage(message);
}

public void resetChat(String error) {


getMessageManager().sendResetMessage(error);
}
public void resetMessage() {
getMessageManager().sendResetMessage("Left");
}

public void addErrorMessage(String message) {


getMessageManager().sendErrorMessage(message);
}

public void updatePlayerState(String playerId, String state) {


Log.d(getClass().getSimpleName(), "updatePlayerState: " + playerId + ": " + state);
getMessageManager().sendPlayerStatusMessage(playerId, state);
}

public MessageManager getMessageManager() {


return MessageManager.getInstance();
}

The above JNI bridge is backed by a pure C++ implementation file that calls into the NetworkManager.cpp,
which in turn calls the Party APIs.
Here's an example snippet that shows the various layers:
The NetworkManager Java interface exposes a method to join a Party Network.

public native boolean joinNetwork(String networkId);

The implementation of the joinNetwork is in the C++ layer in PartyDemo.cpp shown below.
JNIEXPORT jboolean JNICALL
Java_com_microsoft_playfab_party_sdk_NetworkManager_joinNetwork(
JNIEnv* env,
jobject thiz,
jstring networkId
)
{
if (g_isRunning && g_initializeCompleted)
{
Managers::Get<NetworkManager>()->Initialize(g_playfabTitleId.c_str());
const char* networkNameCStr = env->GetStringUTFChars(networkId, NULL);
g_networkName = networkNameCStr;
env->ReleaseStringUTFChars(networkId, networkNameCStr);
g_isSpinDone = false;
Managers::Get<PlayFabManager>()->GetDescriptor(
g_networkName,
[](std::string networkDescriptor)
{
SendSysLogToUI("OnGetDescriptorForConnectTo : %s", networkDescriptor.c_str());
g_networkDescriptor = networkDescriptor;
ReleaseSpin();
}
);

HoldSpin();
// When network connection is not stable, waiting for ConnectToNetwork callback will cost longer
time.
// To avoid App UI busy waiting, return to UI after ConnectToNetwork returns.
Managers::Get<NetworkManager>()->ConnectToNetwork(
g_networkName.c_str(),
g_networkDescriptor.c_str(),
[]()
{
OnNetworkConnected(g_networkName);
SendSysLogToUI("OnConnectToNetwork succeeded");
},
[](PartyError error)
{
SendSysLogToUI("OnConnectToNetworkFailed %s", GetErrorMessage(error));
ResetChat(GetErrorMessage(error));
});

return true;
}
else
{
SendSysLogToUI("Please waiting for initialization done.");
return false;
}
}

In the code snippet above, the joinNetwork calls into NetworkManager::CreateAndConnectToNetwork() which in
turn calls the raw Party API exposed in Party.h

void
NetworkManager::CreateAndConnectToNetwork(
const char *networkId,
std::function<void(std::string)> callback,
std::function<void(PartyError)> errorCallback
)
{
DEBUGLOG("NetworkManager::CreateAndConnectToNetwork()\n");

PartyNetworkConfiguration cfg = {};

// Setup the network to allow the maximum number of single-device players of any device type
// Setup the network to allow the maximum number of single-device players of any device type
cfg.maxDeviceCount = c_maxNetworkConfigurationMaxDeviceCount;
cfg.maxDevicesPerUserCount = 1;
cfg.maxEndpointsPerDeviceCount = 1;
cfg.maxUserCount = c_maxNetworkConfigurationMaxDeviceCount;
cfg.maxUsersPerDeviceCount = 1;

//Get the uid from the local chat control


PartyString uid = nullptr;
PartyError err = m_localUser->GetEntityId(&uid);

if (PARTY_FAILED(err))
{
DEBUGLOG("GetUserIdentifier failed: %s\n", GetErrorMessage(err));
errorCallback(err);
return;
}

// Setup the network invitation configuration to use the network id as an invitation id and allow anyone
to join.
PartyInvitationConfiguration invitationConfiguration{
networkId, // invitation identifier
PartyInvitationRevocability::Anyone, // revokability
0, // authorized user count
nullptr // authorized user list
};

// Initialize an empty network descriptor to hold the result of the following call.
PartyNetworkDescriptor networkDescriptor = {};

// Create a new network descriptor


err = PartyManager::GetSingleton().CreateNewNetwork(
m_localUser, // Local User
&cfg, // Network Config
0, // Region List Count
nullptr, // Region List
&invitationConfiguration, // Invitation configuration
nullptr, // Async Identifier
&networkDescriptor, // OUT network descriptor
nullptr // applied initialinvitationidentifier.
);

if (PARTY_FAILED(err))
{
DEBUGLOG("CreateNewNetwork failed: %s\n", GetErrorMessage(err));
errorCallback(err);
return;
}

// Connect to the new network


if (InternalConnectToNetwork(networkDescriptor, networkId, errorCallback))
{
m_state = NetworkManagerState::WaitingForNetwork;
m_onnetworkcreated = callback;
m_onnetworkcreatederror = errorCallback;
m_onnetworkconnectedError = errorCallback;
}
}

In a similar way, each method in the NetworkManager JNI interface is mapped to Party API via the PartyDemo
and NetworkManager.

Next steps
In this article we saw how to get started integrating the Party library into your Android application. Please refer
to Quickstart For PlayFab Party for getting set up with the rest of the building blocks of PlayFab Party.
iOS getting started
5/24/2022 • 4 minutes to read • Edit Online

This document lists the basic prerequisites and requirements necessary to integrate PlayFab Party into your iOS
applications. Once you've set up your system according to this document, please have a look at the Quickstart
for PlayFab Party for getting set up with the building blocks of PlayFab Party.

Prerequisites
Before you start this tutorial, please ensure that the following prerequisites have been met:
1. You have created a PlayFab developer account
2. You've created a PlayFab Title and your title has been allow-listed for PlayFab Party
3. You have Xcode version 10.2.1 installed
4. You have access to the PlayFab Party platforms repository
5. You have created an apple developer account that can be used to sign your app for deployment.
NOTE: If you're planning to use the XCode simulator for testing, you'll need to target your application for 64-bit
($(ARCHS_STANDARD_64_BIT)) architecture. 32-bit simulators are currently not supported.

Including the required libraries and header files


You'll need to include the following header files from the [PlayFab Party distribution repository]
(https://github.com/PlayFab/PlayFabParty/releases).
LIB Files
1. Party.a
2. libcrypto.a
3. libssl.a

NOTE
The SSL libs are built from Open SSL version XXX. Please use an OpenSSL version that is XXX or higher

Header includes
Party headers
Note that in addition to the lib files and headers above, you'll also need the libs and headers for PlayFab SDK
and any other platform-specific dependencies your app needs. Please take a look at the project file organization
for the Swithc Sample for more info.

Steps to get PlayFab Party working on iOS


Since the core Party library is written using C++, it is directly accessible from objective C++ code. For
convenience, we've made a simple Objective-C++ wrapper class to access the Party lib functionality. At a high
level, you'll want a class that has access to Party API methods to create a network, connect to a network, and
send messages across a network. We've achieved this in our demo app via the SimpleClientClass.
//
// SimpleClient.h
// chatdemo_ios

#import <Foundation/Foundation.h>
#import "ChatEventHandler.h"

@interface SimpleClient : NSObject

@property (nonatomic) id<ChatEventHandler> chatEventHandler;

-(void) initialize;
-(void) setHandler:(id<ChatEventHandler>) messageHandler;
-(void) signInLocalUser;

-(void) createNetwork:(NSString*) networkId;


-(void) joinNetwork:(NSString*) networkId;
-(void) leaveNetwork;

-(void) sendTextAsVoice:(NSString*) text;


-(void) sendTextMessage:(NSString*) text;
-(void) setLanguageCode:(int) languageIndex;
-(NSArray *) getLanguageOptions;
-(int) getDefaultLanguageIndex;

-(NSString*) getSelectedUserName;

-(void) tick;

+(void) globalInitialize;
+(void) globalShutdown;

@end

The above object bridge is backed by a pure C++ implementation file that calls into the NetworkManager.cpp ,
which in turn calls the Party APIs.
Here's an example snippet that shows the various layers:
The SimpleClient objective-C interface exposes a method to initialize Bumblelion.

// In SimpleClient.h
-(void) createNetwork:(NSString*) networkId;

The implementation of the SimpleClient also includes a reference to the C++ object which calls into Party APIs
via the network manager.

// In SimpleClient.mm

@interface SimpleClient ()

@end

@implementation SimpleClient

SimpleClientImpl* m_impl;

The SimpleClientImpl is a C++ class that class that does the heavy lifting of creating the Party network as shown
in the code snippet below:
void
SimpleClientImpl::CreateNetwork(
std::string &networkId
)
{
if (g_isRunning && g_initializeCompleted)
{
Managers::Get<NetworkManager>()->Initialize(c_pfTitleId);
m_messageHandler->OnStartLoading();
Managers::Get<NetworkManager>()->CreateAndConnectToNetwork(
networkId.c_str(),
[this, networkId](std::string message)
{
this->SendSysLogToUI("create network: %s", message.c_str());
Managers::Get<PlayFabManager>()->SetDescriptor(
networkId,
message,
[this, message](void)
{
m_messageHandler->OnEndLoading();
this->SendSysLogToUI("set network descriptor %s", "successed");
std::string l_message = message;
m_messageHandler->OnNetworkCreated(l_message);
});
},
[this](PartyError error)
{
m_messageHandler->OnEndLoading();
this->SendSysLogToUI("create network failed: %s", GetErrorMessage(error));
});
}
}

In the code snippet above, the SimpleClient calls into NetworkManager::CreateAndConnectToNetwork() which in
turn calls the raw Party API exposed in Party.h

void
NetworkManager::CreateAndConnectToNetwork(
const char *networkId,
std::function<void(std::string)> callback,
std::function<void(PartyError)> errorCallback
)
{
DEBUGLOG("NetworkManager::CreateAndConnectToNetwork()\n");

PartyNetworkConfiguration cfg = {};

// Setup the network to allow the maximum number of single-device players of any device type
cfg.maxDeviceCount = c_maxNetworkConfigurationMaxDeviceCount;
cfg.maxDevicesPerUserCount = 1;
cfg.maxEndpointsPerDeviceCount = 1;
cfg.maxUserCount = c_maxNetworkConfigurationMaxDeviceCount;
cfg.maxUsersPerDeviceCount = 1;

//Get the uid from the local chat control


PartyString uid = nullptr;
PartyError err = m_localUser->GetEntityId(&uid);

if (PARTY_FAILED(err))
{
DEBUGLOG("GetUserIdentifier failed: %s\n", GetErrorMessage(err));
errorCallback(err);
return;
}

// Setup the network invitation configuration to use the network id as an invitation id and allow anyone
// Setup the network invitation configuration to use the network id as an invitation id and allow anyone
to join.
PartyInvitationConfiguration invitationConfiguration{
networkId, // invitation identifier
PartyInvitationRevocability::Anyone, // revokability
0, // authorized user count
nullptr // authorized user list
};

// Initialize an empty network descriptor to hold the result of the following call.
PartyNetworkDescriptor networkDescriptor = {};

// Create a new network descriptor


err = PartyManager::GetSingleton().CreateNewNetwork(
m_localUser, // Local User
&cfg, // Network Config
0, // Region List Count
nullptr, // Region List
&invitationConfiguration, // Invitation configuration
nullptr, // Async Identifier
&networkDescriptor, // OUT network descriptor
nullptr // applied initialinvitationidentifier.
);

if (PARTY_FAILED(err))
{
DEBUGLOG("CreateNewNetwork failed: %s\n", GetErrorMessage(err));
errorCallback(err);
return;
}

// Connect to the new network


if (InternalConnectToNetwork(networkDescriptor, networkId, errorCallback))
{
m_state = NetworkManagerState::WaitingForNetwork;
m_onnetworkcreated = callback;
m_onnetworkcreatederror = errorCallback;
m_onnetworkconnectedError = errorCallback;
}
}

In a similar way, each method in the SimpleClient objective-C interface is mapped to Party API via the
SimpleClientImpl and NetworkManager .

Next steps
In this article we saw how to get started integrating the Party library into your iOS application. Please refer to
Quickstart for PlayFab Party for getting set up with the rest of the building blocks of PlayFab Party.
Party Unity plugin overview
5/24/2022 • 4 minutes to read • Edit Online

The PlayFab Party Unity SDK plugin is a Unity C# wrapper on top of a native Party C++ library created for the
convenience of Unity game developers.
It enables you to make use of Party and Party Cognitive Services in your Unity game. This includes multiplayer
networking, chat messages and data exchange, cross-talk, cross-play, accessibility features like real-time text
chat translation and voice transcription services. It is designed for developing games on multiple platforms.
PlayFab Party Unity plugin works alongside the PlayFab "core" Unity SDK plugin which provides other PlayFab
functionalities such as economy, leaderboards, and more. For more information, see PlayFab Unity SDK and
PlayFab Unity SDK documentation.
Party Unity plugin is available for download as a Unity Asset package. It is currently supported for developing
games on the following platforms:
Microsoft Game Core (GDK)*, Windows, iOS, Android: https://github.com/playfab/PlayFabPartyUnity (public
access)
Sony PlayStation®:
PS4: https://dev.azure.com/PlayFabPrivate/PS4/_git/PlayFabPartyUnityPS4 (restricted access by
request to Microsoft Representative)
PS5: https://dev.azure.com/PlayFabPrivate/PS5/_git/PlayFabPartyUnityPS5 (restricted access by
request to Microsoft Representative)
Nintendo Switch™: https://dev.azure.com/PlayFabPrivate/Switch/_git/PlayFabPartyUnitySwitch (restricted
access by request to Microsoft Representative)
*- The underlying Party libraries for GDK are not included in plugin (see below).

What API features are provided by Party Unity plugin?


Game networking
VoIP
Support for the following platforms:
GDK:
Xbox Series X|S
Xbox One
PC
Windows
iOS
Android
PS4
PS5
Switch
Support for cross-play & cross-talk across the above platforms
Party Cognitive Services
Real-time text chat translation
Real-time voice chat transcription
Real-time voice chat translation
Text-to-speech synthesis

What is included in Party Unity plugin?


Simplified top-level Party API written in Unity C# provided by PlayFabMultiplayerManager class and prefab
for easier integration of user's Unity game with the core features of Party library
C# interop layer providing managed-code interface to the underlying native (C++) Party library API. It is
used by the top-level C# API.
Underlying native (C++) Party binaries for each supported platform:
Party DLL libraries for Windows
Party iOS Framework libraries for iOS (device and simulator)
Party AAR library archive for Android
Party DLL libraries for Microsoft Game Core are NOT included. They are distributed with GDK and
must be copied to plugin before building user's Unity project (see details in README file included with
plugin)
Party dynamic libraries for PS4, PS5
Party static libraries for Switch
PlayFab "core" Unity SDK plugin (can be updated independently if needed)
Xbox Live authenication and policy provider API, currently supported on GDK platform only

Party Unity plugin versions and compatibility between platforms


Party Unity plugin is published and available for download at several distribution points (Git repos), depending
on the platform. Access to some distribution points is restricted and requires a request to your Microsoft
Representative.
In order to provide a better guidance on compatibility between versions downloaded from different distribution
points, and reflect a reference to a specific version of the underlying native library, Party Unity plugin follows a
custom versioning scheme.
Party Unity plugin versioning scheme

X.X.X.Y-(distribution-point-indicator).Z

For example, 1.5.0.3-main.0 (a version downloaded from the main public GitHub repo) or 1.5.0.3-ps5.0 (a
version with Party binaries only for PS5, downloaded from a repo with restricted access).
Version components:
X.X.X - the lowest version of the underlying Party library across all supported platforms. This is used for
general reference consistency with a version of the underlying C++ library. In the example above, the version
of an included Party libary for each platform is 1.5.0 or higher.
Y - an incremental index of any modifications in the Party Unity C# layer, for any given X.X.X part of the
version.
(distribution-point-indicator) - a mnemonic code for tracking which distribution point a particular Party
Unity plugin package was downloaded from. It differs by distribution point, e.g. main (main public
distribution GitHub repo), ps5 (Microsoft Azure DevOps repo with restricted access for PS5 developers), etc.
Z - an incremental index of any modifications unique to the distribution point (e.g. Party binaries
updated/patched for a specific platform only).
A higher number in any version component means a newer version, by significance from left to right.
Compatibility between versions from different distribution points
Regardless of a distribution point a Party Unity plugin is downloaded from, it is guaranteed to be fully
compatible with a Party Unity plugin downloaded from any other distribution point, if the first four numbers
( X.X.X.Y ) of their version are the same . Compatible versions from different distribution points can be
imported into user's Unity project in any order without a risk of overwriting/breaking one another, as their
shared code should be identical. Though each of them may have some additional (not shared) files, specific to a
particular platform, which shouldn't overlap.
For example, you can import all the following versions of Party Unity plugin in your Unity project, in any
sequential order, if you are targeting iOS, PS5 and Switch:
1.5.0.3-main.0 (imports Party binaries for iOS, among other files)
1.5.0.3-ps5.0 (imports Party binaries for PS5, among other files)
1.5.0.3-sw.0 (imports Party binaries for Switch, among other files)

The shared (cross-platform) Unity C# code included in each of these plugins will be the same.

Which versions of Unity are supported?


We strive to support all recent versions of Unity starting with Unity 2017, however your choice may be limited
by availability of a Unity development add-on for each particular platform, please see corresponding Unity
documentation. That, in turn, may also limit your choice of the platform SDK. In general, we test Party Unity
plugin with one of the most recent versions of Unity development add-ons available for each platform. We
encourage our customers to report any build or runtime issues with any new version of Unity Editor, Unity add-
on or a platform SDK.

Pricing
VoIP and Game Networking functionality is free for users signed in with an Xbox Live account
(currently suppor ted on GDK platform only).
Party Cognitive Services and other services may have a cost associated with them. For details, see Billing for
PlayFab Party or reach out to your Microsoft Representative.
Quickstart: PlayFab Party Unity Plugin
5/24/2022 • 7 minutes to read • Edit Online

Get started with the PlayFab Party Unity plugin. Follow steps below to install the package and try out example
code for a basic task.
This quickstart helps you make your first API calls using the Party SDK for Unity. Before continuing, make sure
you have completed Getting started for developers and Quickstart: PlayFab Client library for C# in Unity, which
ensures you have a PlayFab account and are familiar with logging into PlayFab from your game and the PlayFab
Game Manager.

NOTE
If you intend to use this plugin to develop games based on the Microsoft Game Development Kit (GDK) you need to
acquire and install the GDK separately. Please also see details about Unity add-on for Game Core on Xbox consoles.

Requirements
A PlayFab developer account.
An installed copy of the Unity Editor. To install Unity for personal use via Unity Hub, or Unity+ for
professional use, see Download Unity. Check on Unity support in documentation of your specific
platform if needed. The minimum supported Unity version is Unity 2017 LTS.
A Unity Project – this can be any of the following:
A brand new project: For more information, see Starting Unity for the first time.
A guided tutorial project. For more information, see Getting Started with Unity.
An existing project.
The PlayFab "core" Unity3D SDK. For information about installing the Unity3D SDK, see the "Download
and install PlayFab SDK" section of Quickstart: PlayFab Client library for C# in Unity.

Download and install the PlayFab Party Unity plugin


Following the steps to download and install the PlayFab Party Unity plugin.
1. Download the PlayFab Party Unity Plugin Asset Package (use a distribution point depending on your
platform).
2. Impor tant! Please see information in README file published with plugin. It is tailored to each particular
version and may include important instructions specific to your platform.
3. Open your Unity Project.
4. Navigate to the location where you saved the .unitypackage and double-click it to open the import dialog.
5. To import the PlayFab Party Unity Plugin into your project, select Impor t .

Set up your scene


This part of the guide shows you how to add the PlayFabMultiplayerManager to your scene to enable you to call
PlayFab Party APIs from Unity.
Before you can create a network, you must have a PlayFab player logged in . For information about logging
in a player, see Making your first API call in Quickstart: PlayFab Client library for C# in Unity.
1. In the Unity editor, in the Project window, navigate to Assets > PlayFabPar tySDK > Prefabs .
2. From the Prefabs folder, drag and drop the PlayFabMultiplayerManager into your scene in the
Hierachy window.
3. Create an empty Game Object in your scene called "HelloPartyLogic".
4. Select the HelloPartyLogic Game Object to open the Inspector .
5. Select Add Component .
6. Type "HelloPartyLogic" and press enter to show the new script menu.
7. Press enter again to create the new script, HelloPartyLogic.cs.
8. Find the script in the Project window and double-click it to edit the script.
9. Add the following using statement to your script:

using PlayFab;
using PlayFab.Party;
using PlayFab.ClientModels;

10. Add the following code in the Start method to log into PlayFab.

// Log into playfab


var request = new LoginWithCustomIDRequest { CustomId = UnityEngine.Random.value.ToString(),
CreateAccount = true };
PlayFabClientAPI.LoginWithCustomID(request, OnLoginSuccess, OnLoginFailure);

11. Add the following methods to the class.

private void OnLoginSuccess(LoginResult result)


{
}

private void OnLoginFailure(PlayFabError error)


{
}

NOTE
You might receive the following errors:

Error CS0227 Unsafe code may only appear if compiling with /unsafe
The plugin requires unsafe code because it interops with a native DLL.

Mismatch between the processor architecture of the project being built "MSIL" and the processor
architecture of the reference "XGamingRuntime", "AMD64".

The Microsoft GDK and Windows only support x64.


To resolve these issues:
1. In the Unity Editor, select File > Build Settings.
2. Select your platform. Then from the Architecture dropdown, select either x86_64 or x64.
3. Select Player Settings.
4. In the right pane, select Other Setting.
5. Find the Allow unsafe Code setting and select it.
6. Close the Build Settings and Project Settings windows.

Connecting to a network
This part of the guide shows you how to Create and Join a network.
1. Open the HelloPartyLogic.cs script. In the OnLoginSuccess method, add the following code to create and
join a network:

PlayFabMultiplayerManager.Get().CreateAndJoinNetwork();
PlayFabMultiplayerManager.Get().OnNetworkJoined += OnNetworkJoined;

2. To define the OnNetworkJoined event handler, add the following code to the class:

private void OnNetworkJoined(object sender, string networkId)


{
// Print the Network ID so you can give it to the other client.
Debug.Log(networkId);
}

3. Save and click Play in the Unity Editor. The Network ID displays in the Console window.

Joining an existing network


This part of the guide shows you how to join an existing network that another client created.
1. Open the HelloPartyLogic.cs script. In the OnLoginSuccess method, add the following code to Join a
network:

string networkId = "<your network id>";


PlayFabMultiplayerManager.Get().JoinNetwork(networkId);

2. To define an event that fires when your local client joins the network, add the following code to the
OnLoginSuccess method:

PlayFabMultiplayerManager.Get().OnNetworkJoined += OnNetworkJoined;

3. To define the OnNetworkJoined event handler, add the following code to the class:.

private void OnNetworkJoined(object sender, string networkId)


{
// Print the Network ID so you can give it to the other client.
Debug.Log("Network joined!");
}

There are many ways to get the Network ID from the host to other players who want to join. Please refer
to the sample in this Unity plugin for an example of how to do that.
4. Save and select Play in the Unity Editor. The string "Network joined!" displays in the Console window.
Accessing other players
This part of the guide shows you how to access other players on the network, including the local player.
To listen for new players joining and leaving the network, register for the OnRemotePlayerJoined and
OnRemotePlayerLeft events.
1. Open the HelloPartyLogic.cs script. In the OnLoginSuccess method, add the following code to Create and
Join a network:

PlayFabMultiplayerManager.Get().OnRemotePlayerJoined += OnRemotePlayerJoined;
PlayFabMultiplayerManager.Get().OnRemotePlayerLeft += OnRemotePlayerLeft;

2. Add the following methods to the class:

private void OnRemotePlayerLeft(object sender, PlayFabPlayer player)


{
}

private void OnRemotePlayerJoined(object sender, PlayFabPlayer player)


{
}

3. To access the local player, add the following code to the OnRemotePlayerJoined method:

var localPlayer = PlayFabMultiplayerManager.Get().LocalPlayer;

The PlayFabPlayer class contains properties for identifying the player, muting, and rendering their chat state in a
chat UI.

Sending and receiving data messages


This part of the guide shows you how to send and receive data messages. Before you can start sending and
receiving data messages, you must join a network.
1. Open the HelloPartyLogic.cs script. In the OnLoginSuccess method, add the following code to listen for
data messages:

PlayFabMultiplayerManager.Get().OnDataMessageReceived += LocalPlayer_OnDataMessageReceived;

2. Add the OnDataMessageRecieved event handler to the class:

private void OnDataMessageReceived(object sender, PlayFabPlayer from, byte[] buffer)


{
Debug.Log(Encoding.Default.GetString(buffer));
}

3. To send a data message, add the following code to the Update method:

if (Input.GetButtonDown("Fire1"))
{
byte[] requestAsBytes = Encoding.UTF8.GetBytes("Hello (data message)");
PlayFabMultiplayerManager.Get().SendDataMessageToAllPlayers(requestAsBytes);
}
Save HelloPartyLogic.cs and select Play in the Unity Editor.
1. In a second client, use the code shown above in Connect to a network to create and join a network.
2. Copy the Network ID returned to your first client and connect to the network.
3. Click on the scene to send a message. "Hello (data message)" displays in the Console window.

Sending and receiving chat messages


This part of the guide shows you how to send and receive chat messages and mute remote players. In addition
to text chat, Party automatically enables voice chat between players.
Before you can start sending and receiving chat messages, you must join a network.
1. Open the HelloPartyLogic.cs script. In the OnLoginSuccess method, add the following code to listen for
chat messages:

PlayFabMultiplayerManager.Get().OnChatMessageReceived += OnChatMessageReceived;

2. Add the event handler OnChatMessageReceived to the class;

private void OnChatMessageReceived(object sender, PlayFabPlayer from, string message, ChatMessageType


type)
{
Debug.Log(message);
}

Save HelloPartyLogic.cs and press Play in the Unity Editor.


1. In a second client, use the code shown above in Connect to a network to create and join a network.
2. Copy the Network ID returned to your first client and connect to the network.
3. When you click on your scene, it sends a message and which displays in the Console window.
4. If you want to give your players the option to mute other players, set the IsMuted property to true.

private void OnRemotePlayerJoined(object sender, PlayFabPlayer player)


{
// This player will not be able to send text or voice communication.
// Data messages can still be sent.+
player.IsMuted = true;
}

Connecting to a network with custom peer connectivity configuration


options
This part of the guide shows you how to Create and Join a network with custom peer connectity configuration
options. The default option is P2P, however, using any combination of the flags presented here:
DirectPeerConnectivityOptions, the user can modify this option. The example below shows how P2P is set.
1. Open the HelloPartyLogic.cs script. In the OnLoginSuccess method, add the following code to create and
join a network:
PlayfabNetworkConfiguration networkConfiguration = new PlayfabNetworkConfiguration();
networkConfiguration.DirectPeerConnectivityOptions =
PARTY_DIRECT_PEER_CONNECTIVITY_OPTIONS_ANY_PLATFORM_TYPE |

PARTY_DIRECT_PEER_CONNECTIVITY_OPTIONS_ANY_ENTITY_LOGIN_PROVIDER;
PlayFabMultiplayerManager.Get().CreateAndJoinNetwork(networkConfiguration);
PlayFabMultiplayerManager.Get().OnNetworkJoined += OnNetworkJoined;
PlayFab Party Unity SDK
5/24/2022 • 2 minutes to read • Edit Online

Classes
NAME DESC RIP T IO N

PlayFabLocalPlayer

PlayFabMultiplayerManager

PlayFabPlayer

Enums
NAME DESC RIP T IO N

AccessibilityMode Options that specify which accessibility settings are enabled.

ChatMessageType The type of delivery guarantee for a message.

ChatState The visual state of the player for rendering in the game's UI.

DeliveryOption The type of delivery guarantee for a message.

DirectPeerConnectivityOptions Flags controlling the attempted use of direct peer-to-peer


connectivity among devices in a network.

LogLevelType The amount of logging that is enabled.

PlayFabMultiplayerManagerErrorType The types of errors PlayFabMultiplayerManager can raise.

PlayFabMultiplayerManagerState The possible states that PlayFabMultiplayerManager can be


in.
PlayFab Party Unity plugin release notes
5/24/2022 • 2 minutes to read • Edit Online

1.7.0.1
Enabled peer-to-peer connection on supported platforms, except from mobile ones, by default.

1.5.0.3
Party Unity SDK plugin becomes generally available (GA) to developers on platforms:
Windows, iOS, Android: https://github.com/playfab/PlayFabPartyUnity
Sony PlayStation®:
PS4: https://dev.azure.com/PlayFabPrivate/PS4/_git/PlayFabPartyUnityPS4 (restricted access)
PS5: https://dev.azure.com/PlayFabPrivate/PS5/_git/PlayFabPartyUnityPS5 (restricted access)
Nintendo Switch™: https://dev.azure.com/PlayFabPrivate/Switch/_git/PlayFabPartyUnitySwitch (restricted
access)
New features in GA
Ability to set a language for the local player, before creating or joining a Party
Optional translation of incoming text chat messages to local language, using Party Cognitive Services
Speech-to-text (STT): optional transcription of incoming audio chat into text chat messages in local language,
using Party Cognitive Services (incurs additional cost if exceeds free quota)
Text-to-speech (TTS): optional synthesization of speech, conversion of outgoing text chat messages into
audible form received by other players (incurs additional cost if exceeds free quota)
Bug fixes
Numerous bug fixes and stability improvements since pre-release.
Overview
5/24/2022 • 2 minutes to read • Edit Online

The PlayFab Online Subsystem (PF OSS) enables you to make use of Multiplayer features like Lobby,
Matchmaking, Party and Azure Cognitive Services in your Unreal Engine 4 (UE4) game. These features include
cross-talk, cross-play, and accessibility features like real-time text chat translation and voice transcription
services. It is currently designed for use when developing PC, Xbox, Steam and Nintendo Switch games. This
subsystem layer works seamlessly on top of the existing Epic provided base Online Subsystem (OSS) GDK.
PlayFab OSS compliments the base OSS by adding support for PlayFab Lobby, Matchmaking, Party networking
and Voice over Internet Protocol (VOIP).
PlayFab OSS works alongside the PlayFab SDK marketplace plugin, which provides other PlayFab functionalities
such as economy, leaderboards, and more. For more information, see PlayFab SDK on the UE4 Marketplace
(external site).

What is included in the Online Subsystem?


Create, join and search lobbies
Quick matchmaking
Invite friends to game lobby
Game networking
VOIP
Support for the following platforms:
Xbox Series X GDK
PC GDK
Xbox One GDK
PC Steam
Nintendo Switch
Support for cross-play & cross-talk across the above platforms
Azure Cognitive Services
Real-time text chat translation
Real-time voice chat transcription
Real-time voice chat transcription translation
Text-to-speech synthesis

Which versions of Unreal Engine are supported?


We officially support 4.27 and 4.26, however 4.27 is the recommended version. Crossplay between different
platforms does not work on 4.26, but it does on 4.27. If you are on an earlier version of Unreal Engine 4, the OSS
can be backported with minimal work. Refer to the Using older versions of Unreal Engine 4 page for more
details.
NOTE: If you are using a version of UE4 earlier than 4.25plus, you will have to rename all references to GDK to
Anvil using find & replace all.

Which versions of the Microsoft Game Development Kit (GDK) are


supported?
PC
Recommended: June 2021 GDK (2021.06)
Minimum: November 2020 GDK (2020.11)
When utilizing a GDK version earlier than 2020.11 on PC, reach out to your Microsoft
Representative for further guidance.
Xbox GDK:
Recommended: June 2021 GDK (2021.06)
Minimum: June 2021 GDK (2021.06)
XDK is supported on older version(1.07 and earlier) of the OSS, refer Using older version for further details.

Which version of the Nintendo Switch SDKs are supported?


Recommended: Refer to the UEBuild.cs file in the UnrealBuildTool folder for the Switch.

Pricing
VOIP and Game Networking functionality is free for users signed in with an Xbox Live account,
regardless of platform.
Cognitive services and other services may have a cost associated with them. For details, see Billing for PlayFab
Party or reach out to your Microsoft Representative.
QuickStart: PlayFab Online Subsystem (OSS)
5/24/2022 • 3 minutes to read • Edit Online

This quickstart guide helps you set up and use Multiplayer features such as Lobby, Matchmaking and Party for
Xbox, PC, and Nintendo Switch games built using Unreal Engine 4. For the full list of supported platforms and
versions in UE4, see Supported platforms.
After following the relevant steps below for your target platforms, you'll be ready to start using the OSS.
Authentication, networking, VOIP, grouping into lobbies, and matchmaking will be handled on your behalf with
no other changes required.

Download and install PlayFab Online Subsystem


Go to UE OSS PlayFab to download or clone PlayFab Online SubSystem source.

What you need


PlayFab Title ID: If you don't have a Title ID configured for PlayFab Party, see Enabling PlayFab Party.
GDK and PC
Specific platform PlayFab Multiplayer and Par ty libraries: These files are provided with the source in
Download and install PlayFab Online Subsystem. If you need updated Party library files, then see Obtaining
PlayFab Party libraries.
Private platforms
Nuget.exe Find the location of Nuget.exe on your machine and add it to the PATH environment variable.
Specific platform PlayFab Multiplayer and Par ty libraries: run SetUpPrivateOSS.ps1 located in the
OnlineSubsystemPlayFab folder. This script will pull the binaries and source code for the supported
private platforms. You must have access to our private repositories.

Initial setup
Copy the OnlineSubsystemPlayFab folder and its contents from to your UE4 directory under
Engine\Plugins\Online
Apply the following changes to the Plugins section of your ".uproject" file. This will add the
OnlineSubsystemPlayFab to your plugin list.
You may remove any platforms that you're not shipping on
{
"Name": "OnlineSubsystemPlayFab",
"Enabled": true,
"WhitelistPlatforms": [
"XboxOneGDK",
"WinGDK",
"XSX",
"Win64",
"Switch"
],
"SupportedTargetPlatforms": [
"XboxOneGDK",
"WinGDK",
"XSX",
"Win64",
"Switch"
]
}

Game Configuration
No matter which platform you're targeting, your game will need to configure certain PlayFab specific values
in your intended platform target's INI file (located at [yourGameDirectory]/Platforms/[yourPlatform]/Config).
Xbox Series X GDK: XSXEngine.ini
PC GDK: WinGDKEngine.ini
Xbox One GDK: XboxOneGDKEngine.ini
PC Steam: WindowsEngine.ini
Nintendo Switch SwitchEngine.ini
Replace the INI sections in the config if they already exist (for example, Engine.GameEngine) with the ones
below.
Ensure you replace all the <REPLACE ME> fields with your data:
[OnlineSubsystemPlayFab]
bEnabled=true
PlayFabTitleID=<REPLACE ME with your PlayFab title ID>
MaxDeviceCount=<REPLACE ME with your max player count (note: split screen is still 1 device). In the example
of an 8 player game, this would be 8.>
MaxDevicesPerUserCount=<REPLACE ME with your max player count per box (note: split screen is still 1 device)
In the example of an 8 player game, this would be 1.>
MaxEndpointsPerDeviceCount=<REPLACE ME with your max player count per box (note: split screen is still 1
device) In the example of an 8 player game, this would be 1.>
MaxUserCount=<REPLACE ME with your max player count (note: split screen is still 1 device) In the example
of an 8 player game, this would be 8.>
MaxUsersPerDeviceCount=<REPLACE ME with your max player count per box (note: split screen is still 1 device)
In the example of an 8 player game, this would be 1.>
DirectPeerConnectivityOptions=<REPLACE ME with your connectivity options, in the form of an array of
strings. The default case corresponds to the following:
+DirectPeerConnectivityOptions=AnyPlatformType
+DirectPeerConnectivityOptions=AnyEntityLoginProvider>

[/Script/OnlineSubsystemPlayFab.PlayFabNetDriver]
NetConnectionClassName="OnlineSubsystemPlayFab.PlayFabNetConnection"
ReplicationDriverClassName="<REPLACE ME with your existing replication driver class name>"
ConnectionTimeout=15.0
InitialConnectTimeout=30.0

[/Script/Engine.GameEngine]
!NetDriverDefinitions=ClearArray
+NetDriverDefinitions=
(DefName="GameNetDriver",DriverClassName="OnlineSubsystemPlayFab.PlayFabNetDriver",DriverClassNameFallback="
OnlineSubsystemUtils.IpNetDriver")

Platform Specific Considerations


With all that done, we're nearly finished. There are only a few key platform-specific parameters left that must be
set.
GDK
If you're developing games using GDK, define the platform services and, optionally, set your GDK sandbox:

[OnlineSubsystem]
DefaultPlatformService=PlayFab
NativePlatformService=GDK

[OnlineSubsystemPlayFab]
Sandbox=<Optional, REPLACE ME with the sandbox Id used for the title under development >

Steam
If you're developing games for Win64 with Steam, define your platform services:

[OnlineSubsystem]
DefaultPlatformService=PlayFab
NativePlatformService=Steam

Switch
See the ReadMe.md file that comes with the Switch PlayFab OSS for more details.
Cross-platform
Finally, if your game makes use PlayFab's cross-platform networking support, define which platforms you'll
permit to connect:
[/Script/OnlineSubsystemUtils.OnlineEngineInterfaceImpl]
!CompatibleUniqueNetIdTypes=ClearArray
+CompatibleUniqueNetIdTypes=STEAM
+CompatibleUniqueNetIdTypes=GDK
+CompatibleUniqueNetIdTypes=SWITCH

This completes the setup of OSS required to be used in your game. Good luck!
Obtaining PlayFab Party libraries
5/24/2022 • 2 minutes to read • Edit Online

You will require PlayFab Party headers, library and DLL in order to be able to utilize this subsystem. See below
for the options available to you.

Using the GDK


PlayFab Party is included with the GDK and the OSS will use this version by default when building.

Using the XDK


PlayFab Party headers, libraries, and DLLs are not included in the XDK. You must perform the steps outlined
below in the XDK: Bringing your own PlayFab Par ty librar y section to obtain the XDK version of PlayFab
Party.
This can be obtained by extracting the PlayFab Party NuGet package and PlayFab Party Xbox Live NuGet package

XDK: Bringing your own PlayFab Party library


Navigate to the OnlineSubsystemPlayFabParty directory (where OnlineSubsystemPlayFabParty.uplugin is
located)
Create a new Platforms folder
Create a new XDK folder inside the above folder
Create these three new folders inside the XDK folder:
Include
Lib
Redist
Copy the following files into the relevant folder:
Include: All Party & PartyXboxLive header files
Lib: Party.lib & PartyXboxLive.lib
Redist: Party.dll, PartyXboxLive.dll, Party.pdb and PartyXboxLive.pdb
XDK builds will now use this version of PlayFab Party.
Introduction to Cognitive Services
5/24/2022 • 2 minutes to read • Edit Online

The PlayFab Party Cognitive Services Interface includes functions that allow for the configuration and use of the
accessibility features provided by PlayFab Party.
These features include:
Real-time text chat translation
Real-time voice chat transcription
Real-time voice chat transcription translation
Text-to-speech synthesis

Pricing
Cognitive Services and other services beyond core VOIP and game networking functionality may have a cost
associated with them. Please visit the Billing for PlayFab Party page for more details or reach out to your
Microsoft Representative.

Using the Cognitive Services Interface


To use the Cognitive Services Interface in your game, add the following block of code to your game's Build.cs file.

if (Target.bGenerateProjectFiles || (Target.Type != TargetType.Game && Target.Type != TargetType.Client))


{
PublicDefinitions.Add("WITH_OSS_PLAYFAB_COGNITIVESERVICES=0");
}
else
{
PublicDefinitions.Add("WITH_OSS_PLAYFAB_COGNITIVESERVICES=1");

PublicDependencyModuleNames.Add("OnlineSubsystemPlayFab");
PrivateDependencyModuleNames.Add("HTTP");
}

Additionally, you can wrap any game code with #if WITH_OSS_PL AYFAB_COGNITIVESERVICES to prevent
compilation errors on platforms that do not use Cognitive Services.

SetTextChatTranslationOptions
SetTextChatTranslationOptions allows chat translation to be toggled on or off.

SetVoiceChatTranscriptionOptions
SetVoiceChatTranscriptionOptions is required for enabling and configuring voice transcription.
bTranscribeSelf - Transcriptions of the local chat control will be generated and provided to the same local
chat control
bTranscribeOtherChatControlsWithMatchingLanguages - Transcriptions of other chat controls with
the same language as the local chat control will be generated and provided to the local chat control
bTranscribeOtherChatControlsWithNonMatchingLanguages - Transcriptions of other chat controls
with languages that are different from the local chat control's language will be generated and provided to the
local chat control
bTranslateToLocalLanguage - Transcriptions will be translated to the local chat control's language

SetTextToSpeechOptions
SetTextToSpeechOptions is required for enabling and configuring text to speech.
ETextToSpeechType::Narration - Render audio to the local chat control's audio output
ETextToSpeechType::VoiceChat - Render audio to chat controls which the local chat control is configured
to send audio to

SendTextAsVoice
Generates text to speech audio that is sent to all other clients connected to the PlayFab Party network. Text as
Voice must be enabled via a call to SetTextToSpeechOptions before calling SendTextAsVoice

SendChatText
Sends chat text string to all other clients connected to the PlayFab Party network.
Using older versions of Unreal Engine 4
5/24/2022 • 2 minutes to read • Edit Online

While not officially supported by the PlayFab Online Subsystem (OSS), it is entirely possible to use it on older
versions of Unreal Engine 4. Core networking functionality will migrate back to earlier versions of Unreal Engine
4 with minor tweaks to interface function names & signatures, with certain instances renamed or removed to
match older versions of the Unreal Engine 4 OSS interface.

XDK support on version 1.07 and earlier


Apply the changes below to the Game (not Engine) INI file 'XboxOneEngine.ini'
Replace the INI sections if they already exist (e.g. Engine.GameEngine)
Ensure you replace all the <REPLACE ME> fields with your data.

[OnlineSubsystem]
DefaultPlatformService=PlayFab
NativePlatformService=Live

[OnlineSubsystemPlayFab]
bEnabled=true
PlayFabTitleID=<REPLACE ME with your PlayFab title ID>
MaxDeviceCount=<REPLACE ME with your max player count (note: split screen is still 1 device). In the example
of an 8 player game, this would be 8.>
MaxDevicesPerUserCount=<REPLACE ME with your max player count per box (note: split screen is still 1 device)
In the example of an 8 player game, this would be 1.>
MaxEndpointsPerDeviceCount=<REPLACE ME with your max player count per box (note: split screen is still 1
device) In the example of an 8 player game, this would be 1.>
MaxUserCount=<REPLACE ME with your max player count (note: split screen is still 1 device) In the example
of an 8 player game, this would be 8.>
MaxUsersPerDeviceCount=<REPLACE ME with your max player count per box (note: split screen is still 1 device)
In the example of an 8 player game, this would be 1.>

[/Script/OnlineSubsystemPlayFab.PlayFabNetDriver]
NetConnectionClassName="OnlineSubsystemPlayFab.PlayFabNetConnection"
ReplicationDriverClassName="<REPLACE ME with your existing replication driver class name>"
ConnectionTimeout=15.0
InitialConnectTimeout=30.0

[/Script/Engine.GameEngine]
!NetDriverDefinitions=ClearArray
+NetDriverDefinitions=
(DefName="GameNetDriver",DriverClassName="OnlineSubsystemPlayFab.PlayFabNetDriver",DriverClassNameFallback="
OnlineSubsystemUtils.IpNetDriver")

Enabling cross-generational play between XDK and GDK


The default game implementation in Unreal Engine 4 validates that an incoming remote Net ID is of the same
subsystem type as the local instance, as such cross-play between XDK and GDK will have different types and
requires you to make one of the following changes:
Override the function within your GameMode and implement a PreLogin function which doesn’t require this
check or pass a nullptr to the base function for NetID, skipping the check.
You may have already this class overridden
Edit the base function AGameMode::PreLogin to remove the OSS type check (bUniqueIdCheckOk )
PlayFab Unreal Engine 4 OnlineSubsystem release
notes
5/24/2022 • 2 minutes to read • Edit Online

Refer to QuickStart: PlayFab Online Subsystem (OSS) for download and install instructions.

2.0.0
UE4 engine OSS PlayFab is updated to use Multiplayer features offered by Azure PlayFab such as Lobby,
Matchmaking along with PlayFab Party. This replaces the Xbox provided MPSD with Azure PlayFab Lobby and
XBL Smart match with Azure Matchmaking service.
XDK is not longer supported for this version of the OSS

1.0.7
UE4 Engine version 4.26 is the recommnded version to use with this version of OnlineSubsystemPlayfab.
Notes:
Rename OnlineSubsystemPlayFabParty to OnlineSubsystemPlayfab.
Xbox XDK Prerequisites
5/24/2022 • 2 minutes to read • Edit Online

Xbox One exclusive resource application network manifest templates


In its app package manifest, the app should declare the internetClientServer and privateNetworkClientServer
capabilities, because an application using Party requires connecting to and accepting connections from network
resources, both over the Internet and the local network. The app should also declare the microphone device
capability, as Party requires access to microphone devices to support voice chat. For more detail about these
capability settings, see the platform documentation.
The following snippet shows the nodes that must exist under the Package/Capabilities node in order to enable
connectivity and voice communication. An Xbox One exclusive resource application that uses PlayFab Party must
ensure certain socket description and template content is included in its "network manifest" extension of the app
package manifest. See the platform documentation for more detail on network package manifests.
<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/2010/manifest"
xmlns:mx="http://schemas.microsoft.com/appx/2013/xbox/manifest"
IgnorableNamespaces="mx">
...
<Capabilities>
<Capability Name="internetClientServer" />
<Capability Name="privateNetworkClientServer" />
<DeviceCapability Name="microphone" />
</Capabilities>
...
<Applications>
<Application ...>
<Extensions>
<mx:Extension Category="windows.xbox.networking">
<mx:XboxNetworkingManifest>
<mx:SocketDescriptions>
<mx:SocketDescription Name="PlayFabPartyUdpInitiatorToCloudService" SecureIpProtocol="Udp"
BoundPort="0">
<mx:AllowedUsages>
<mx:SecureDeviceSocketUsage Type="Initiate" />
<mx:SecureDeviceSocketUsage Type="SendInsecure" />
<mx:SecureDeviceSocketUsage Type="ReceiveInsecure" />
</mx:AllowedUsages>
</mx:SocketDescription>
<mx:SocketDescription Name="PlayFabPartyUdpAcceptorOnCloudService" SecureIpProtocol="Udp"
BoundPort="1-65535">
<mx:AllowedUsages>
<mx:SecureDeviceSocketUsage Type="Accept" />
<mx:SecureDeviceSocketUsage Type="SendInsecure" />
<mx:SecureDeviceSocketUsage Type="ReceiveInsecure" />
</mx:AllowedUsages>
</mx:SocketDescription>
</mx:SocketDescriptions>
<mx:SecureDeviceAssociationTemplates>
<mx:SecureDeviceAssociationTemplate Name="PlayFabPartyClientToCloudServiceUdp"
InitiatorSocketDescription="PlayFabPartyUdpInitiatorToCloudService"
AcceptorSocketDescription="PlayFabPartyUdpAcceptorOnCloudService" MultiplayerSessionRequirement="None">
<mx:AllowedUsages>
<mx:SecureDeviceAssociationUsage Type="InitiateFromMicrosoftConsole" />
<mx:SecureDeviceAssociationUsage Type="AcceptOnOtherDevice" />
</mx:AllowedUsages>
</mx:SecureDeviceAssociationTemplate>
</mx:SecureDeviceAssociationTemplates>
</mx:XboxNetworkingManifest>
</mx:Extension>
</Extensions>
</Application>
</Applications>
</Package>

Next steps
Quickstart for PlayFab Party
Xbox Requirements
Using MPSD
Xbox Requirements
5/24/2022 • 10 minutes to read • Edit Online

If your game is targeting Xbox consoles, it must adhere to a set of requirements to ensure consistent
functionality and behavior when interacting with Xbox Live. This set of requirements is listed in the Xbox
Requirements (XRs for short). XRs interact and overlap with the policies that are required to make use of Xbox
Live in your game on PC and other platforms. Here we describe best practices for PlayFab Party that will help
you comply with these requirements.
For quick reference, refer to the following table which matches PlayFab Party scenarios to the XRs they address:

SC EN A RIO XR

Secure Data Transmission XR-012

Aligning PlayFab Party with an Xbox Live user's chat settings XR-015, XR-045
and privileges

Maintaining a multiplayer session document XR-067

Identifying players in a cross-network game session XR-007

Respecting cross-network communication permissions for XR-007


Xbox Live users

Guarding against direct connections between Xbox consoles XR-007


and other devices

Use PlayFab Party invitations to restrict access to networks XR-007


when cross-play is not allowed

Keeping in sync with Xbox Live profile settings XR-048

Supporting platform multiplayer join flows XR-064, XR-124

Friends lists XR-007, XR-070

Supporting voice chat XR-072

Honoring Xbox Live service retry policy and service access XR-074, XR-132
limitations

PlayFab Party Xbox Live Helper library


Alongside the core PlayFab Party library, we offer an Xbox Live Helper library which is designed to help comply
with Xbox Live policies and, by extension, XRs. Use of this helper library is not required but is highly
recommended and considered best practice. The examples presented here will assume use of the Xbox Live
Helper library.

Secure data transmission


PlayFab Party's endpoints and chat controls enable your game to securely transmit game and chat data to
remote clients. By default, all game and chat data is routed through the PlayFab Party relay service which
protects clients from denial-of-service attacks.
Therefore, using PlayFab Party satisfies the game and chat data transmission requirements of XR-012. Refer to
the XR-012 technical documentation for further requirements outside the scope of PlayFab Party.

Aligning PlayFab Party with an Xbox Live user's chat settings and
privileges
PlayFab Party uses an opt-in model of chat communication and, by default, restricts all communications between
two chat controls to the set of communications which both participants have enabled. For more information, see
the documentation for chat permissions and muting.
PlayFab Party's Xbox Live Helper library indicates which set of chat permissions should be enabled to match the
preferences and privileges of the Xbox Live users currently communicating in the Party session. For more
information, see the documentation about respecting an Xbox Live user's privacy settings and permissions.
By properly making use of PlayFab Party and the Xbox Live Helper library, your game can entirely meet the
requirements specified by XR-015 and can meet the relevant communication requirements specified by XR-045.
Refer to the XR-045 technical documentation for further requirements outside the scope of PlayFab Party.

Maintaining a multiplayer session document


PlayFab Party does not provide any sort of Xbox user roster. It relies on your game using the Multiplayer Session
Directory service (MPSD) to maintain a roster and associate Party network activity with the users in the game
session. PlayFab Party will advertise remote endpoints and chat controls as they come and go from Party
networks. The PlayFab Entity IDs associated with these objects should be matched with the Xbox users in the
MPSD document to recognize which PlayFab Party objects represent Xbox users in the game session. For cross-
play scenarios, a PlayFab Entity not associated with an Xbox user may represent a user in another multiplayer
ecosystem.
To recognize Xbox users, you should build mappings between PlayFab Entity IDs and Xbox Live users. To achieve
this, it is recommended that you store the session's list of Xbox Live users in an MPSD document and translate
those Xbox Live users to PlayFab Entity IDs using the Xbox Live Helper library. For examples, see Mapping
between Xbox Live User IDs and PlayFab Entity IDs.
In addition to providing the Party network's roster, MPSD documents also drive many multiplayer experiences in
the Xbox multiplayer ecosystem such as matchmaking, platform invites, recent player lists, and join-in-progress.
For more information on how to incorporate Party networks into these MPSD flows, see Using PlayFab Party
with MPSD.
For more information on MPSD features, see its overview documentation.

IMPORTANT
This section provides best practices when using PlayFab Party together with MPSD, but PlayFab Party itself does not
implicitly satisfy the MPSD requirements of XR-067. Refer to the XR-067 technical documentation for information on
satisfying these requirements.

Using Xbox clients in cross-play Party networks


For cross-play scenarios, please keep in mind the following best practices when interacting with the Xbox Live
ecosystem.
IMPORTANT
This section provides best practices for using PlayFab Party in cross-play scenarios with Xbox Live, but use of PlayFab
Party does not implicitly satisfy the cross-play requirements of XR-007. Refer to the XR-007 technical documentation for
information on satisfying these requirements.

Identifying players in a cross-network game session


Unique players should be identifiable and distinguishable across multiplayer ecosystems. For this purpose,
PlayFab Party provides PlayFab Entity IDs on the various objects which might be associated with users in your
session: PartyLocalUser , PartyEndpoint , PartyChatControl .
Cross-network display names are not provided by the PlayFab Party API. When displaying Xbox users in UI, you
should use their gamertag and the gamertag should be resolved from the Xbox User ID in the MPSD document.
Non-Xbox users should be presented in UI based on the guidelines in XR-007. In the absence of a platform-
provided display name, PlayFab provides support for display names via GetPlayerProfile. When joining a
network, a player should post their display name in a shared session document for other players to see.
Though the PlayFab Party library associates some of its objects with PlayFab users (via PlayFab Entity IDs), the
library does not provide functionality to identify which multiplayer ecosystems a PlayFab user might be
associated with. To distinguish Xbox Live PlayFab users from users in other multiplayer ecosystems, it is
recommended to cross-reference the PlayFab Entity IDs in a Party network with MPSD. For more information on
distinguishing Xbox Live players from non-Xbox Live players via MPSD, see the section on Maintaining a
multiplayer session document.
For more information on requirements around identifying users in cross-play networks with Xbox Live, refer to
XR-007.
Respecting cross-network communication permissions for Xbox Live users
PlayFab Party does not implicitly comply with Xbox Live's cross-network communication restrictions. Therefore,
the PlayFab Party Xbox Live Helper library provides functionality for querying an Xbox Live user's cross-network
communication permissions. You must use this information to conform to the cross-network communication
requirements specified in XR-007.
See Respecting cross-network communications for more information.
Guarding against direct connections between Xbox consoles and other devices.
PlayFab Party's use of secure relays for data transmission keeps clients protected from direct connections
between Xbox consoles and other devices. Therefore, use of PlayFab Party implicitly provides compliance with
the direct connection requirements of XR-007 and XR-012.
See Secure Data Transmission for more information.
Use PlayFab Party invitations to restrict access to networks when cross-play is not allowed.
Xbox Live users require cross-network privileges to interact with non-Xbox Live users in cross-network game
sessions. PlayFab Party does not implicitly comply with these cross-network restrictions (outlined in XR-007),
therefore this privilege must be queried outside of the PlayFab Party library. When these privileges are not
given, you should restrict the Party network to only allow the Xbox Live users known in the game session's
MPSD document. You can accomplish this by augmenting our sample join-in-progress flow to use Party
invitations that only allow known Xbox users to join the network.
First, ensure that the Party network is created with a restricted invitation.
PartyString networkCreatorEntityId;
RETURN_VOID_IF_FAILED(m_localPartyUser->GetEntityId(&networkCreatorEntityId));

PartyInvitationConfiguration newNetworkInitialInvite{};
newNetworkInitialInvite.identifier = nullptr; // let Party select the invitation identifier for simplicity
newNetworkInitialInvite.revocability = PartyInvitationRevocability::Anyone; // the initial invitation must
be revocable by anyone

// this initial invitation only allows the original xbl user creating the network
newNetworkInitialInvite.entityIdCount = 1;
newNetworkInitialInvite.entityIds = &networkCreatorEntityId;

PartyError error = PartyManager::GetSingleton().CreateNewNetwork(


m_localPartyUser,
&networkConfiguration,
0,
nullptr,
&newNetworkInitialInvite,
nullptr,
nullptr,
nullptr);

Similar to the join-in-progress flow, when a new Xbox user wants to join the network, they will first add
themselves to the session document. When the player that wants to allow them into the network sees the
update, they will update the set of invitations to reflect the session document. This will ensure that only users in
the session document (which are guaranteed to be Xbox Live users) can join the network.

void
OnSessionDocumentUpdated(
PartyNetwork* network,
uint32_t usersInDocumentCount,
const uint64_t* usersInDocument
)
{
PartyInvitationConfiguration newInvite{};
newInvite.identifier = nullptr; // let Party select the invitation identifier for simplicity
newInvite.revocability = PartyInvitationRevocability::Creator; // must be revocable by the creator only

// the updated invite should contain all users currently in the document
std::vector<PartyString> entityIdsInDocument;
for (uint32_t i = 0; i < usersInDocumentCount; ++i)
{
uint64_t xboxUserId = usersInDocument[i];
// Call title-defined xuid->entityid mapping helper
PartyString xboxUserEntityId = GetEntityIdFromXboxUserId(xboxUserId);
if (xboxUserEntityId != nullptr)
{
entityIdsInDocument.push_back(xboxUserEntityId);
}
else
{
DEBUGLOG("User %llu did not have a matching entity ID.", xboxUserId);
}
}
newInvite.entityIdCount = entityIdsInDocument.size();
newInvite.entityIds = entityIdsInDocument.data();

// Create a new invitation which includes all of the users currently in the document
PartyInvitation* newInvitation;
PartyError error = network->CreateInvitation(
m_localUser,
&newInvite,
nullptr,
&newInvitation);
if (PARTY_FAILED(error))
{
DEBUGLOG("PartyNetwork(0x%p)::CreateInvitation failed! (error=0x%x)", network, error);
return;
}

// Post the invitation's id somewhere that it can be seen by anyone trying to join/rejoin
PostInvitationToMPSD(newInvite);

// Cleanup previous invitations. This isn't strictly necessary, but is a good practice.
uint32_t invitationCount;
PartyInvitationArray invitations;
error = network->GetInvitations(&invitationCount, &invitations);
if (PARTY_FAILED(error))
{
DEBUGLOG("PartyNetwork(0x%p)::GetInvitations failed! (error=0x%x)", network, error);
return;
}

for (uint32_t i = 0; i < invitationCount; ++i)


{
if (invitations[i] == newInvite)
{
continue; // don't prune the old invitation
}

PartyInvitation* oldInvitation = invitations[i];

error = network->RevokeInvitation(m_localUser, oldInvitation, nullptr);


if (PARTY_FAILED(error))
{
DEBUGLOG("PartyNetwork(0x%p)::RevokeInvitation failed! (err=0x%x)", network, error);
}
}
}

NOTE
Because you will need to translate between Xbox Live User IDs and PlayFab Entity IDs, it is recommended to build a
mapping between the two. See Mapping between Xbox Live User IDs and PlayFab Entity IDs for examples on how to do
this.

Keeping in sync with Xbox Live profile settings


PlayFab Party, by default, conforms to the profile settings requirements in XR-048. The library does not keep a
persistent cache of any Xbox Live profile settings. When profile settings are needed for PlayFab Party's use, the
settings are queried from Xbox Live and remain valid for the lifetime of the PlayFab Party API object associated
with the setting, but will not persist across multiple instances of the object.
For information on using Xbox Live profile settings data outside of PlayFab Party, see the XR-048 technical
documentation.

Supporting platform multiplayer join flows


On Xbox, players can join multiplayer games via the join-in-progress and platform invitation features. PlayFab
Party does not integrate with these platform features directly, but supports their use via PartyNetworkDescriptor
and PartyInvitation objects. PartyNetworkDescriptor objects provide the connection information necessary for
a remote user to find and connect to the Party network and can be serialized via
PartyManager::SerializeNetworkDescriptor . PartyInvitation objects provide remote users with an ID which is
used to authenticate into and join a Party network. To enable remote users to join multiplayer games via join-in-
progress and platform invites, integrate the serialized network descriptor and Party invitation identifier into your
pre-existing flows. Example flows can also be found in the Using PlayFab Party with MPSD document.
For more information on platform multiplayer join flow requirements, see the XR-064 and XR-124 technical
documentation.

Friends lists
Even though PlayFab Party does not interact natively with friends lists on any platform, multiplayer games may
still need to consider friends lists for different scenarios. For information on requirements and guidance when
interacting with Xbox Live and cross-network friends lists, see the following documentation:
Xbox Live friends list requirements (XR-070)
Cross-network friends list requirements (XR-007)
Xbox Social Manager
Xbox Live Services API (XSAPI)

Supporting voice chat


All multiplayer games on Xbox must support voice chat. By using PlayFab Party for voice chat, your game
implicitly complies with the requirements specified by XR-072. For information on how PlayFab Party supports
voice chat for Xbox Live see the following documentation:
Understanding chat
Respecting an Xbox Live user's privacy settings and permissions
Respecting cross-network communication preferences for Xbox Live
XR-072

Honoring Xbox Live service retry policy and service access limitations.
PlayFab Party does not directly interact with Xbox Live services outside of the Xbox Live Helper library. The Xbox
Live Helper library, internally, conforms to the retry policies and access limitations for its relevant Xbox Live
services as outlined in XR-074 and XR-132. As well, you can recognize API failures as a result of complying with
these service policies through the following error codes reported by the Xbox Live Helper library:
PartyXblChatPermissionMaskReason::XboxLiveServiceError and PartyXblStateChangeResult::PartyServiceError.
For more information on complying with these service policies outside of the Xbox Live Helper library, see the
XR-074 and XR-132 technical documentation.
Using PlayFab Party with MPSD
5/24/2022 • 8 minutes to read • Edit Online

Xbox multiplayer scenarios rely on the use of the Multiplayer Session Directory (MPSD) service and MPSD
documents. MPSD documents act as the roster for your current game session and drive multiplayer experiences
such as matchmaking, platform invites, recent player lists, and join-in-prgress.
In this document we will describe how you can incorporate PlayFab Party into common multiplayer flows that
require MPSD.
This document does not provide an in-depth discussion of MPSD and all of it's capabilities. For more
information, refer to the MPSD documentation.

Matchmaking
Here's a simplified flow for how to use matchmaking and MPSD together with PlayFab Party:
1. Players will create and gather into MPSD sessions that represent the groups they want playing together
across matchmaking sessions. Players will gather into these sessions by using Xbox's invite and join
features.
2. Those player groups will submit tickets to the matchmaking service which will gather compatible player
groups into a matchmaking session. This matchmaking session will, itself, be represented by a new
session document which the players will then join. Players must also listen for changes to this session
document.
3. Once the matchmaking session has been finalized and the roster is locked, the title must elect one of the
members of the matchmaking session to set up the PlayFab Party network. A simple strategy for
selecting the Party network creator is to use the first member of the matchmaking MPSD session
document.
4. The selected member will create the network with an initial PartyInvitation that restricts network access
to only the members of the matchmaking session. Once the network has successfully completed creation,
the selected member should post the resulting network descriptor and Party invitation to the session
document as a session property for other members to use.

void
OnMatchmakingSessionFinalized(
uint32_t usersInSessionCount,
const uint64_t* usersInSession
)
{
PartyInvitationConfiguration initialInvite{};
initialInvite.identifier = nullptr; // let Party select the invitation identifier for simplicity
initialInvite.revocability = PartyInvitationRevocability::Anyone; // must be revocable by anyone

// the updated invite should contain all users in the matchmaking session
std::vector<PartyString> entityIdsInSession;
for (uint32_t i = 0; i < usersInSessionCount; ++i)
{
uint64_t xboxUserId = usersInSession[i];
// Call title-defined xuid->entityid mapping helper
PartyString xboxUserEntityId = GetEntityIdFromXboxUserId(xboxUserId);
if (xboxUserEntityId != nullptr)
{
entityIdsInSession.push_back(xboxUserEntityId);
}
else
{
DEBUGLOG("User %llu did not have a matching entity ID.", xboxUserId);
}
}
initialInvite.entityIdCount = entityIdsInSession.size();
initialInvite.entityIds = entityIdsInSession.data();

// This is an asynchronous call. It will be completed when StartProcessingStateChanges generates


a
// PartyCreateNewNetworkCompletedStateChange struct
PartyError error = PartyManager::GetSingleton().CreateNewNetwork(
m_localPartyUser,
&networkConfiguration,
0,
nullptr,
&initialInvite,
nullptr,
nullptr,
nullptr);
if (FAILED(error))
{
DEBUGLOG("PartyManager::CreateNetwork failed! 0x%08x\n", error);
return;
}
}

void
HandleCreateNewNetworkCompleted(
const PartyCreateNewNetworkCompletedStateChange& createNewNetworkCompletedStateChange
)
{
if (createNewNetworkCompletedStateChange.result == PartyStateChangeResult::Succeeded)
{
// The network was created successfully! Post the networks descriptor and invitation

char serializedDescriptor[c_maxSerializedNetworkDescriptorStringLength + 1];


PartyError error = PartyManager::SerializeNetworkDescriptor(
&createNewNetworkCompletedStateChange.networkDescriptor,
serializedDescriptor);
if (PARTY_FAILED(error))
{
DEBUGLOG("PartyManager::SerializeNetworkDescriptor failed: 0x%08x\n", error);
return;
}

UpdateSessionProperty(
"PartyNetworkDescriptor", // arbitrary property name
serializedDescriptor);

UpdateSessionProperty(
"PartyInitialInvitation", // arbitrary property name
createNewNetworkCompletedStateChange.appliedInitialInvitationIdentifier);
}
else
{
// The network was not created successfully.
// Please refer to CreateNewNetwork reference documentation for retry guidance
}
}

5. When each member sees the session document updated, they may use the network descriptor and
invitation to connect to and join the network.
void
OnNetworkInformationPostedToSessionDocument(
PartyString serializedNetworkDescriptor,
PartyString invitationId
)
{
PartyNetworkDescriptor networkDescriptor;
PartyError error = PartyManager::DeserializeNetworkDescriptor(serializedNetworkDescriptor,
&networkDescriptor);
if (PARTY_FAILED(error))
{
DEBUGLOG("PartyManager::DeserializeNetworkDescriptor failed: 0x%08x\n", error);
return;
}

// attempt to connect to the network


PartyNetwork* network;
error = PartyManager::GetSingleton().ConnectToNetwork(
&networkDescriptor,
nullptr,
&network);
if (PARTY_FAILED(error))
{
DEBUGLOG("PartyManager::ConnectToNetwork failed: 0x%08x\n", error);
return;
}

// immediately queue an authentication on the network we've attempted to connect to.


error = network->AuthenticateLocalUser(
m_localUser,
invitationId,
nullptr);
if (PARTY_FAILED(error))
{
DEBUGLOG("PartyNetwork::AuthenticateLocalUser failed: 0x%08x\n", error);
return;
}
}

NOTE
Here we've presented one flow for incorporating matchmaking and MPSD with PlayFab Party. The core ideas of this flow
can be extended to other flows you might be interested in with MPSD, but presenting all possible flows is outside the
scope of this documentation. For more information, see the full MPSD documentation.

Platform invites
Here's a flow for how to incorporate Xbox platform invites into PlayFab Party:
1. PlayerA creates an MPSD session document, listens for session changes, and a creates a Party network.
When the Party network creation has completed, *PlayerA *posts the network descriptor and an initial
invite (if necessary) to the MPSD session document.
void
OnSessionDocumentCreated()
{
// This is an asynchronous call. It will be completed when StartProcessingStateChanges generates
a
// PartyCreateNewNetworkCompletedStateChange struct
PartyError error = PartyManager::GetSingleton().CreateNewNetwork(
m_localPartyUser,
&networkConfiguration,
0,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr);
if (FAILED(error))
{
DEBUGLOG("PartyManager::CreateNetwork failed! 0x%08x\n", error);
return;
}
}

void
HandleCreateNewNetworkCompleted(
const PartyCreateNewNetworkCompletedStateChange& createNewNetworkCompletedStateChange
)
{
if (createNewNetworkCompletedStateChange.result == PartyStateChangeResult::Succeeded)
{
// The network was created successfully! Post the networks descriptor and invitation

char serializedDescriptor[c_maxSerializedNetworkDescriptorStringLength + 1];


PartyError error = PartyManager::SerializeNetworkDescriptor(
&createNewNetworkCompletedStateChange.networkDescriptor,
serializedDescriptor);
if (PARTY_FAILED(error))
{
DEBUGLOG("PartyManager::SerializeNetworkDescriptor failed: 0x%08x\n", error);
return;
}

UpdateSessionProperty(
"PartyNetworkDescriptor", // arbitrary property name
serializedDescriptor);
}
else
{
// The network was not created successfully.
// Please refer to CreateNewNetwork reference documentation for retry guidance
}
}

2. When PlayerA wants to invite PlayerB to the Party network, PlayerA initiates a platform invite to PlayerB
via in-game or console UI.
3. PlayerB receives the platform invite which includes an "invite handle" that PlayerB can use to find
PlayerA's MPSD session document.
4. PlayerB joins the session document and listens for changes.
5. PlayerA sees PlayerB join the session document. PlayerA creates a new invitation for PlayerB to use and
posts that invitation to the session document
void
OnUserJoinedSessionDocument(
PartyNetwork* network,
uint64_t newSessionMemberXboxUserId
)
{
std::string newMemberIdString = std::to_string(newSessionMemberXboxUserId);

// Specify our own invitation id so we don't have to query for it after the invitation has been
created.
// Here we will specify the invite id with the format "InviterXboxUserID_InviteeXboxUserID" so
that we can
// ensure this invitation ID doesn't clash with the invitations other members might try and
create for this user.
std::string invitationId = std::to_string(m_localXboxUserId) + "_" + newMemberIdString;

PartyInvitationConfiguration newInvite{};
newInvite.identifier = invitationId.c_str();
newInvite.revocability = PartyInvitationRevocability::Creator; // must be revocable by the
creator only

// Call title-defined xuid->entityid mapping helper


PartyString newSessionMemberEntityId = GetEntityIdFromXboxUserId(newSessionMemberXboxUserId);
newInvite.entityIdCount = 1;
newInvite.entityIds = &newSessionMemberEntityId;

// Create a new invitation which includes all of the users currently in the document
PartyInvitation* newInvitation;
PartyError error = network->CreateInvitation(
m_localUser,
&newInvite,
nullptr,
&newInvitation);
if (PARTY_FAILED(error))
{
DEBUGLOG("PartyNetwork(0x%p)::CreateInvitation failed! (error=0x%x)", network, error);
return;
}

// Post the invitation to the local user's member property store in the session document, key'd
by the invitee's
// xbox user id. This will let the invitee recognize when an invitation is intended for them.
UpdateMemberProperty(
newMemberIdString.c_str(),
invitationId.c_str());
}

6. PlayerB sees the invitation posted to the session document and uses it to join the Party network.
void
OnRemoteMemberPropertyUpdated(
PartyString memberPropertyKey,
PartyString memberPropertyValue
)
{
// The member property update signifies a new invitation, if the remote member updated a property
that matches
// our xbox user id.
if (memberPropertyKey == std::to_string(m_localXboxUserId))
{
OnUserInvitationPostedToSessionDocument(memberPropertyValue);
}

// ...
}

void
OnUserInvitationPostedToSessionDocument(
PartyString invitationId
)
{
// The network descriptor should have already been posted to the session document before the
invitation.
// Call title-defined function to pull it from the session document.
PartyNetworkDescriptor networkDescriptor = QueryNetworkDescriptorFromSessionDocument();

// attempt to connect to the network


PartyNetwork* network;
error = PartyManager::GetSingleton().ConnectToNetwork(
&networkDescriptor,
nullptr,
&network);
if (PARTY_FAILED(error))
{
DEBUGLOG("PartyManager::ConnectToNetwork failed: 0x%08x\n", error);
return;
}

// immediately queue an authentication on the network we've attempted to connect to.


error = network->AuthenticateLocalUser(
m_localUser,
invitationId,
nullptr);
if (PARTY_FAILED(error))
{
DEBUGLOG("PartyNetwork::AuthenticateLocalUser failed: 0x%08x\n", error);
return;
}
}

IMPORTANT
Invitations created via PartyNetwork::CreateInvitation will become invalid if the PartyLocalUser which created
them leaves the network. Therefore, if a new user adds themselves to a session document but the user which
invited them leaves, it is recommended that the new user remove themselves from the session document and
wait to be re-invited by another user.

Join in-progress
Joining in-progress game sessions is very similar to the platform invite scenario. The core difference is that
instead of PlayerA sending PlayerB an "invite handle", PlayerB will get a "join handle" when they initiate a join-
in-progress from the platform UI. Using this "join handle", the PlayerB will join the session document and listen
for changes. PlayerA will respond by creating and posting a new Party invitation for them to the session
document. PlayerB will see this new invitation alongside the network descriptor and will use it to join the Party
network.

IMPORTANT
Invitations created via PartyNetwork::CreateInvitation will become invalid if the PartyLocalUser which created them leaves
the network. Therefore, if a new user receives a Party invitation from the join-in-progress flow, but cannot use it becaues
the user which created it has left, it is recommended that the new user remove themselves from the session document
and re-join later. This will enable another member of the session to restart the flow and generate a new Party invitation
for this user.

Disconnects and Cleanup


If a player leaves or is otherwise disconnected from a Party network, they should also remove themselves from
any MPSD sessions associated with that Party network. Party network disconnects not initiated by a
PartyNetwork::LeaveNetwork operation are considered fatal. After experiencing a fatal disconnect, a player may
try to re-connect and re-authenticate into the network but must also rejoin the MPSD session.
If a player's connection to an MPSD session is temporarily interrupted, they may get disconnected from that
session. Players can attempt to rejoin the session but, if they fail, should voluntarily remove themselves from the
Party network by calling PartyNetwork::LeaveNetwork.

NOTE
The mechanisms and heuristics which detect disconnects for Party networks and MPSD sessions are different. Even in
scenarios where a player will be disconnected from both the Party network and MPSD session, these disconnect events
are independent, and it is not guaranteed that they occur close to each other in time. Titles should handle the scenario
where a player might only be disconnected from either the Party network or MPSD session.

If the game shuts down, the player will be disconnected from the Party network and MPSD document
automatically, and no further clean up is necessary.
Xbox Live Helper library overview
5/24/2022 • 10 minutes to read • Edit Online

The Xbox Live Helper library for PlayFab Party is designed to help games using PlayFab Party meet Xbox Live
policies related to communication (XR-015 and XR-045). The Xbox Live Helper library is available on Nuget.org.

Compatibility with the PlayFab Party library


While we strive to minimize breaking changes in our APIs, some changes made to the PlayFab Party API might
cause the Xbox Live Helper library to return erroneous values. Refer to the below table to ensure that your
libraries' version are compatible.

XB O X L IVE H EL P ER L IB RA RY P L AY FA B PA RT Y VERSIO N P L AY FA B PA RT Y VERSIO N


VERSIO N 1. 0. 1 1. 3. 0+

1.0.1 ✔

1.1.0 ✔

1.2.0 ✔

1.2.5 ✔

Keeping Track of Xbox Live Users


The PlayFab Party Xbox Live helper must be explicitly informed of the Xbox Live users currently participating in
the Party session. It is recommended that titles achieve this by listening for changes to their multiplayer session
document and reflecting that roster in the Xbox Live Helper library via PartyXblManager::CreateLocalChatUser
and PartyXblManager::CreateRemoteChatUser .
For local users:

void
OnLocalXboxUserAddedToMPSD(
uint64_t xboxUserId
)
{
PartyXblLocalChatUser* localChatUser;
PartyError err = PartyXblManager::GetSingleton().CreateLocalChatUser(xboxUserId, nullptr,
&localChatUser);
if (PARTY_FAILED(err))
{
DEBUGLOG("CreateLocalChatUser failed: %s\n", PartyXblManager::GetErrorMessage(err));
return;
}

At this point, if a PartyLocalChatControl already exists for the corresponding local xbox user, you can associate it
with this PartyXblLocalChatUser via the SetCustomContext methods.

localChatControl->SetCustomContext(localChatUser);
localChatUser->SetCustomContext(localChatControl);
Otherwise you can use this new PartyXblLocalChatUser to generate the chat control and associate them then.
See Creating PartyLocalChatControls from PartyXblLocalChatUsers for more information.
For remote users:

void
OnRemoteXboxUserAddedToMPSD(
uint64_t xboxUserId
)
{
PartyXblChatUser* remoteChatUser;
PartyError err = PartyXblManager::GetSingleton().CreateRemoteChatUser(remoteXboxUserId,
&remoteChatUser);
if (PARTY_FAILED(err))
{
DEBUGLOG("CreateRemoteChatUser failed: %s\n", PartyXblManager::GetErrorMessage(err));
return;
}

At this point, if a PartyChatControl already exists for the corresponding remote xbox user, you can associate it
with this PartyXblChatUser via the SetCustomContext methods.

remoteChatControl->SetCustomContext(remoteChatUser);
remoteChatUser->SetCustomContext(remoteChatControl);

Bear in mind, updates to the session document and updates to the list of remote chat controls may not be
strongly ordered, and you may require similar association logic when processing
PartyChatControlCreatedStateChange updates for remote chat controls.

For both, local and remote chat users, it's important to keep in mind that the core Party library identifies users
and chat controls via PlayFab Entity IDs where as the Xbox Live helper library identifies chat users with Xbox
User IDs. Therefore translating between the two is often necessary. Please refer to Mapping between Xbox Live
User IDs and PlayFab Entity IDs for more information.

Creating PartyLocalChatControls from PartyXblLocalChatUsers


PartyXblLocalChatUser objects are often only useful when associated with PartyLocalUser and
PartyLocalChatControl objects in the Party library. Generating PartyLocalUser and PartyLocalChatControl
objects, requires titles to log in their users to PlayFab and retrieve their user's entityId and
titlePlayerEntityToken . Login can be performed via the PlayFab CPP SDK, but if a title intends to use Xbox Live
credentials to log into PlayFab, they may use PartyXblManager::LoginToPlayFab to avoid pulling in an extra
dependency.
The following sample shows how the Xbox Live Helper library can help you create PartyLocalUser and
PartyLocalChatControl objects, from PartyXblLocalChatUser objects. For more information on creating
PartyXblLocalChatUser objects, see Keeping Track of Xbox Live Users.

err = PartyXblManager::GetSingleton().LoginToPlayFab(localChatUser, nullptr);


if (PARTY_FAILED(err))
{
DEBUGLOG("LoginToPlayFab failed: %s\n", PartyXblManager::GetErrorMessage(err));
return;
}

Shortly after calling PartyXblManager::LoginToPlayFab you will receive a


PartyXblLoginToPlayFabCompletedStateChange containing the result of the login operation.
PartyLocalUser* partyLocalUser;
if (stateChange->stateChangeType == PartyXblStateChangeType::LoginToPlayFabCompleted)
{
auto loginToPlayFabCompleted = static_cast<PartyXblLoginToPlayFabCompletedStateChange*>
(stateChange);
if (loginToPlayFabCompleted->result == PartyXblStateChangeResult::Succeeded)
{
err = PartyManager::GetSingleton().CreateLocalUser(
loginToPlayFabCompleted->entityId,
loginToPlayFabCompleted->titlePlayerEntityToken,
partyLocalUser));
if (PARTY_FAILED(err))
{
DEBUGLOG("CreateLocalUser failed: %s\n", PartyManager::GetErrorMessage(err));
return;
}
}
}

PartyLocalDevice* localDevice;
err = PartyManager::GetSingleton().GetLocalDevice(&localDevice);
if (PARTY_FAILED(err))
{
DEBUGLOG("GetLocalDevice failed: %s\n", PartyManager::GetErrorMessage(err));
return;
}

PartyLocalChatControl* localChatControl;
err = localDevice->CreateChatControl(partyLocalUser, nullptr, nullptr, &localChatControl);
if (PARTY_FAILED(err))
{
DEBUGLOG("CreateChatControl failed: %s\n", PartyManager::GetErrorMessage(err));
return;
}

// We can use the custom context on the PartyXblLocalChatUser to store the PartyLocalChatControl for
easy access
// in the future.
localChatUser->SetCustomContext(localChatControl);

Respecting an Xbox Live user's accessibility preferences


The PartyXblLocalChatUser object exposes some of the accessibility preferences of the Xbox Live user which are
relevant to Party chat sessions. Titles can use this information to provide a better experience to their players by
enabling some of Party's accessibility features right away.

PartyXblAccessibilitySettings accessibilitySettings;
err = localChatUser->GetAccessibilitySettings(&accessibilitySettings);
if (PARTY_FAILED(err))
{
DEBUGLOG("GetAccessibilitySettings failed: %s\n", PartyXblManager::GetErrorMessage(err));
return;
}

if (accessibilitySettings.speechToTextEnabled)
{
PartyVoiceChatTranscriptionOptions option =
PartyVoiceChatTranscriptionOptions::TranscribeOtherChatControlsWithMatchingLanguages;
m_localChatControl->SetTranscriptionOptions(option, nullptr);
}

Respecting an Xbox Live user's privacy settings and permissions


Per Xbox Live policies, titles must not allow communication over Xbox Live when the user's privacy or
permissions do not allow it. The Xbox Live Helper library will help you achieve that by allowing you to query the
most restrictive PartyChatPermissionOptions between two users allowed by Xbox Live policies. Anytime this
value changes, a PartyXblRequiredChatPermissionInfoChangedStateChange will be generated by the library. The
updated PartyChatPermissionOptions can be obtained by a call to
PartyXblLocalChatUser::GetRequiredChatPermissionInfo() .

PartyXblChatUser* remoteChatUser;
PartyError err = PartyXblManager::GetSingleton().CreateRemoteChatUser(remoteXboxUserId,
&remoteChatUser);
if (PARTY_FAILED(err))
{
DEBUGLOG("CreateRemoteChatUser failed: %s\n", PartyXblManager::GetErrorMessage(err));
return;
}

// Once the chat control representing this remote Xbox Live user joins a network, we can use the custom
context
// on the PartyXblChatUser to store the chat control object for quick access in the future.
remoteChatUser->SetCustomContext(m_remotePartyChatControl);

The Xbox Live helper library tracks the privacy and privilege settings for each remote chat user in relation to
each local chat user by communicating with Xbox Live privacy services. Additionally, the library will listen for
changes to these settings by subscribing to (Real-Time Activity)[https://docs.microsoft.com/gaming/xbox-
live/real-time-activity-service/real-time-activity-service_nav] updates. When new remote chat users are added
or when the privacy and privilege relationship between a local chat user and an existing remote chat user
changes, a PartyXblRequiredChatPermissionInfoChangedStateChange will be generated to notify you that an
updated PartyChatPermissionOptions value is now available.
// Wait for PartyXblRequiredChatPermissionInfoChangedStateChange
if (stateChange->stateChangeType == PartyXblStateChangeType::RequiredChatPermissionInfoChanged)
{
auto chatPermissionChanged = static_cast<PartyXblRequiredChatPermissionInfoChangedStateChange*>
(stateChange);

PartyXblLocalChatUser* localChatUser = chatPermissionChanged->localChatUser;


PartyXblChatUser* targetChatUser = chatPermissionChanged->targetChatUser;

PartyXblChatPermissionInfo chatPermissionInfo;
PartyError err = localChatUser->GetRequiredChatPermissionInfo(targetChatUser, &chatPermissionInfo);
if (PARTY_FAILED(err))
{
DEBUGLOG("GetRequiredChatPermissionInfo failed: %s\n", PartyXblManager::GetErrorMessage(err));
return;
}

PartyLocalChatControl* localChatControl;
localChatUser->GetCustomContext(reinterpret_cast<void**>(&localChatControl));
if (PARTY_FAILED(err))
{
DEBUGLOG("GetCustomContext failed: %s\n", PartyXblManager::GetErrorMessage(err));
return;
}

PartyChatControl* targetChatControl;
targetChatUser->GetCustomContext(reinterpret_cast<void**>(&targetChatControl));
if (PARTY_FAILED(err))
{
DEBUGLOG("GetCustomContext failed: %s\n", PartyXblManager::GetErrorMessage(err));
return;
}

localChatControl->SetPermission(targetChatControl, chatPermissionInfo.chatPermissionMask);
if (PARTY_FAILED(err))
{
DEBUGLOG("SetPermission failed: %s\n", PartyXblManager::GetErrorMessage(err));
return;
}
}

The PartyXblChatPermissionInfo structure contains two pieces of information:


A mask that can be either passed as-is to
PartyChatPermissionOptions
PartyLocalChatControl::SetPermission() or that can be used as a binary mask if you already have a
PartyChatPermissionOptions value that you would like to use but want to make sure that you are respecting
Xbox Live policies.
A PartyXblChatPermissionMaskReason value that provides extra information regarding the value of
PartyXblChatPermissionInfo::chatPermissionMask

PA RT Y XB L C H AT P ERM ISSIO N M A SK REA SO N EXP L A N AT IO N

NoRestriction There is no restriction currently applying to this chat


permission.

Determining Communication is restricted while the local user's


communication privilege and privacy settings are being
determined

Privilege Communication is restricted due to the local user's


communication privilege.
PA RT Y XB L C H AT P ERM ISSIO N M A SK REA SO N EXP L A N AT IO N

Privacy Communication is restricted due to the local user's privacy


settings in relation to the target chat user.

InvalidTargetUser Communication is restricted because the target user was not


recognized as valid by Xbox Live services.

XboxLiveServiceError The required chat permission could not be successfully


determined due to issues with Xbox Live services.

UnknownError The required chat permission could not be successfully


determined due to an unknown internal error.

Respecting cross-network communication permissions


Titles that support cross-network play and communication between Xbox Live and non-Xbox Live players need
to check communication permissions prior to allowing communication between those players. The Xbox Live
Helper library provides this information through
PartyXblLocalChatUser::GetCrossNetworkCommunicationPrivacySetting() . This method returns a
PartyXblCrossNetworkCommunicationPrivacySetting enum with three possible value:

PA RT Y XB L C RO SSN ET W O RKC O M M UN IC AT IO N P RIVA C Y SET T I


NG EXP L A N AT IO N

Allowed This Xbox Live user's permissions are set to allow


communication with all cross-network players.

FriendsOnly This Xbox Live user's permissions are set to allow


communication with cross-network friend only.

Disallowed This Xbox Live user's permissions do not allow any


communication with cross-network players.

PartyXblCrossNetworkCommunicationPrivacySetting crossNetworkSetting;
localChatUser->GetCrossNetworkCommunicationPrivacySetting(&crossNetworkSetting);

if (crossNetworkSetting == PartyXblCrossNetworkCommunicationPrivacySetting::Disallowed)
{
m_localChatControl->SetPermissions(crossNetworkChatControl, PartyChatPermissionOptions::None);
}

More information on XR-015 and how it pertains to cross-network play and communication can be found here

Mapping between Xbox Live User IDs and PlayFab Entity IDs
Xbox Live titles using PlayFab Party will often need to translate between Xbox Live Users IDs (used throughout
the Xbox Live ecosystem) and PlayFab Entity IDs (used by PlayFab Party). Using
PartyXblManager::GetEntityIdsFromXboxLiveUserIds , titles can retrieve a list of PlayFab Entity IDs corresponding
to a given list of Xbox Live User IDs. Titles are expected to already have a list of Xbox Live User IDs through the
use of an external roster service, like the Multiplayer Session Directory. By associating the Xbox Live User IDs
from the roster with their PlayFab Entity IDs, we can construct a mapping of all PlayFab Entity IDs corresponding
to your game session's roster. This mapping can then be used to associate PartyEndpoint and PartyChatControl
objects with their corresponding Xbox Live users.
NOTE
Each Xbox Live User ID will only map to a PlayFab Entity ID if this Xbox Live user has already been linked to a PlayFab
account. A PlayFab account is automatically created and linked the first time PartyXblManager::LoginToPlayFab is
called for a given Xbox user. Alternatively, consumers of the PlayFab SDK can use the LoginWithXbox API to achieve the
same results.

The local PartyXblLocalChatUser will be used to authenticate with PlayFab. If the user was not previously logged
in to PlayFab with a call to PartyXblManager::LoginToPlayFab , the Xbox Live Helper library will need to
authenticate the user in the background.
uint32_t userCount;
PartyXblChatUserArray chatUsers;
PartyError err = PartyXblManager::GetSingleton().GetChatUsers(&userCount, &users);
if (PARTY_FAILED(err))
{
DEBUGLOG("GetChatUsers failed: %s\n", PartyXblManager::GetErrorMessage(err));
return;
}

// The list of remote Xbox Live User IDs. This can be populated with arbitrary IDs
// std::vector<uint64_t> remoteXboxLiveUserIds = {2533274792693551, 2814659110958830};
//
// but can also be pulled from the list of remote chat users
std::vector<uint64_t> remoteXboxLiveUserIds;
for (uint32_t i = 0; i < userCount; ++i)
{
PartyXblChatUser* chatUser = users[i];

PartyXblLocalChatUser* localChatUser;
err = chatUser->GetLocal(&localChatUser);
if (PARTY_FAILED(err))
{
DEBUGLOG("PartyChatUser(0x%p)::GetLocal failed: %s\n", chatUser,
PartyXblManager::GetErrorMessage(err));
return;
}

if (localChatUser != nullptr)
{
continue; // ignore local users
}

uint64_t userId;
err = chatUser->GetXboxUserId(&userId);
if (PARTY_FAILED(err))
{
DEBUGLOG("PartyChatUser(0x%p)::GetXboxUserId failed: %s\n", chatUser,
PartyXblManager::GetErrorMessage(err));
return;
}

remoteXboxLiveUserIds.push_back(userId);
}

err = PartyXblManager::GetSingleton().GetEntityIdsFromXboxLiveUserIds(
remoteXboxLiveUserIds.size(),
remoteXboxLiveUserIds.data(),
localChatUser,
nullptr);
if (PARTY_FAILED(err))
{
DEBUGLOG("GetEntityIdsFromXboxLiveUserIds failed: %s\n", PartyXblManager::GetErrorMessage(err));
return;
}

Shortly after calling PartyXblManager::GetEntityIdsFromXboxLiveUserIds you will receive a


PartyXblGetEntityIdsFromXboxLiveUserIdsCompletedStateChange containing the result of the operation. This result
can be used to construct or update your mappings.
// Wait for PartyXblGetEntityIdsFromXboxLiveUserIdsCompletedStateChange
if (stateChange->stateChangeType == PartyXblStateChangeType::GetEntityIdsFromXboxLiveUserIdsCompleted)
{
std::vector<std::pair<uint64_t, std::string>> cachedXboxUserIdToPlayFabEntityIdMap;

auto getEntityIdsFromXboxLiveUserIdsResult =
static_cast<PartyXblGetEntityIdsFromXboxLiveUserIdsCompletedStateChange*>(stateChange);
for (uint32_t i = 0; i < getEntityIdsFromXboxLiveUserIdsResult.entityIdMappingCount; ++i)
{
const PartyXblXboxUserIdToPlayFabEntityIdMapping& idMapping =
getEntityIdsFromXboxLiveUserIdsResult.entityIdMappings[i];

Log(" Xbox Live User ID: %llu", idMapping.xboxLiveUserId);


if (strlen(idMapping.playfabEntityId)) != 0)
{
Log(" PlayFab Entity ID: %s", idMapping.playfabEntityId);
cachedXboxUserIdToPlayFabEntityIdMap.emplace_back(idMapping.xboxLiveUserId,
idMapping.playfabEntityId);
}
else
{
// This Xbox Live User did not have a linked PlayFab Account.
Log(" PlayFab Entity ID: NOT FOUND");
}
}

m_cachedXboxUserIdToPlayFabEntityIdMap = std::move(cachedXboxUserIdToPlayFabEntityIdMap);

With such a mapping, titles can recognize when a Party object represents an Xbox Live user.

uint64_t
GetXboxUserIdFromPlayFabEntityId(
PartyString entityId
)
{
for (const std::pair<uint64_t, std::string>& idMapping : m_cachedXboxUserIdToPlayFabEntityIdMap)
{
const std::string& entityIdForXboxUserId = idMapping.second;
if (entityIdForXboxUserId == entityId)
{
return idMapping.first;
}
}

// Failed to find a matching Xbox User ID. This Entity ID does not represent an Xbox Live user.
return 0;
}

Special considerations for Windows 10 and Windows 7


On Windows, the Xbox Live Helper library needs helps from the title to obtain Xbox Live tokens. The library will
request tokens by generating PartyXblTokenAndSignatureRequestedStateChange . The title can use the Xbox
Authentication Library (XAL) to fulfill these requests. Offloading this work to the title ensures that it remains in
full control of any UI handling and consent prompt that is normally associated with user authentication.
if (stateChange->stateChangeType == PartyXblStateChangeType::TokenAndSignatureRequested)
{
auto tokenAndSignatureRequested = static_cast<PartyXblTokenAndSignatureRequestedStateChange*>
(stateChange);

// Convert the headers to the format XAL expect


std::vector<XalHttpHeader> xalHeaders;
for (uint32_t i = 0; i < stateChange.headerCount; ++i)
{
xalHeaders.push_back({stateChange.headers[i].name, stateChange.headers[i].value});
}

XalUserGetTokenAndSignatureArgs args = {};


args.method = stateChange.method;
args.url = stateChange.url;
args.headerCount = static_cast<uint32_t>(xalHeaders.size());
args.headers = xalHeaders.data();
args.bodySize = stateChange.bodySize;
args.body = static_cast<const uint8_t*>(stateChange.body);
args.forceRefresh = stateChange.forceRefresh != 0;
args.allUsers = stateChange.allUsers != 0;

XAsyncBlock* asyncBlock = new XAsyncBlock;


asyncBlock->queue = m_queue;
HRESULT hr = XalUserGetTokenAndSignatureSilentlyAsync(m_userHandle, &args, asyncBlock);
}

For more guidance on how to retrieve token and signature using XAL, see the Xbox Authentication Library
documentation.
Once you have the token and signature, they can be provided to the Xbox Live Helper library by calling
PartyXblManager::CompleteGetTokenAndSignatureRequest() with the same correlationId that was provided to the
title through the state change.
Xbox Live Helper library release notes
5/24/2022 • 2 minutes to read • Edit Online

The Xbox Live Helper library is available on Nuget.org!

1.2.9
Bug fix for GetEntityIdsFromXboxLiveUserIds crash
Fixed a bug where the async operation started by PartyManager::GetEntityIdsFromXboxLiveUserIds() may
crash on failure.

1.2.5
This release of the Party Xbox Live Helper library includes the following changes:
A small memory leak is fixed.
A bug which prevented some heap allocations from flowing through the memory callbacks set in
PartyXblManager::SetMemoryCallbacks() is fixed.
PartyXblManager::CreateLocalChatUser() will no longer asynchronously fail if Xbox Live services cannot be
queried. In the event of service failures, PartyXblLocalChatUser::GetAccessibilitySettings() will return an
empty PartyXblAccessibilitySettings struct and
PartyXblLocalChatUser::GetCrossNetworkCommunicationPrivacySetting() will return
PartyXblCrossNetworkCommunicationPrivacySetting::Disallowed .

1.2.0
This release of the Party Xbox Live Helper library includes support for the updated chat permission options in
version 1.3.0 of PlayFab Party. For a full list of Party and Party Xbox Live Helper library version compatibility, see
the Party Xbox Live Helper Library overview.

1.1.0
GetEntityIdsFromXboxLiveUserIds API
This release of the Party Xbox Live Helper library introduces the
PartyXblManager::GetEntityIdsFromXboxLiveUserIds() API and associated completion state change,
PartyXblGetEntityIdsFromXboxLiveUserIdsCompleted . This API allows Titles to query the PlayFab Entity Ids
corresponding to a given list of Xbox Live User IDs. For more information, see overview.

1.0.1
LoginToPlayFab API
This release of the Party Xbox Live Helper library introduces the PartyXblManager::LoginToPlayFab() API and
associated completion state change, PartyXblLoginToPlayFabCompletedStateChange . This API provides equivalent
functionality to the PlayFab SDK LoginWithXbox API. For more information, see overview.
PartyXboxLive C/C++ API overview
5/24/2022 • 2 minutes to read • Edit Online

Classes
C L A SS DESC RIP T IO N

PartyXblChatUser The management class for Xbox Live operations related to a


chat user.

PartyXblLocalChatUser The management class for Xbox Live operations related to a


local chat user. Inherits from PartyXblChatUser.

PartyXblManager The primary management class for interacting with the Party
Xbox Live Helper library.

Structures
ST RUC T URE DESC RIP T IO N

PartyXblAccessibilitySettings Accessibility settings associated with an Xbox Live account.

PartyXblChatPermissionInfo Information regarding a required chat permission.

PartyXblHttpHeader Information about an HTTP header.

PartyXblXboxUserIdToPlayFabEntityIdMapping Mapping between an Xbox Live User Id and a PlayFab Entity


Id.

State changes
STAT E C H A N GE DESC RIP T IO N

PartyXblCreateLocalChatUserCompletedStateChange Information specific to the CreateLocalChatUserCompleted


type of state change.

PartyXblGetEntityIdsFromXboxLiveUserIdsCompletedStateCh Information specific to the


ange GetEntityIdsFromXboxLiveUserIdsCompleted type of state
change.

PartyXblLocalChatUserDestroyedStateChange Information specific to the LocalChatUserDestroyed type of


state change.

PartyXblLoginToPlayFabCompletedStateChange Information specific to the LoginToPlayFabCompleted type of


state change.

PartyXblRequiredChatPermissionInfoChangedStateChange Information specific to the


RequiredChatPermissionInfoChanged type of state change.
STAT E C H A N GE DESC RIP T IO N

PartyXblStateChange A generic, base structure representation of an event or


change in state.

PartyXblTokenAndSignatureRequestedStateChange Information specific to the TokenAndSignatureRequested


type of state change.

Enumerations
EN UM ERAT IO N DESC RIP T IO N

PartyXblChatPermissionMaskReason Reasons communication may be restricted.

PartyXblCrossNetworkCommunicationPrivacySetting Possible cross-network communication privacy settings for a


local Xbox Live user.

PartyXblLocalChatUserDestroyedReason Reasons a local chat user object might be destroyed.

PartyXblStateChangeResult Results for operations that generate state changes.

PartyXblStateChangeType The types of state changes that can occur.

PartyXblThreadId Threads that Party Xbox Live Helper library uses for internal
purposes.
Azure PlayFab SDK
5/24/2022 • 2 minutes to read • Edit Online

This topic lists the different flavors of Azure PlayFab SDKs we currently have today.
PlayFab SDK enables you to implement a majority of our features, including LiveOps, economy, matchmaking,
and data analytics.
Access to SDKs for Nintendo Switch, PlayStation 4, PlayStation 5, and Google Stadia requires special approval
and adherence to platform policies. For more information, see Request access for SDKs and samples.
For broad API categories in this SDK, see API REST operation groups.

TIP
Unsure if this is the SDK you need? See SDK overview - PlayFab SDK, Party SDK, Multiplayer Server SDK.

By content
SDK / L IB RA RY P L AT F O RM / EN VIRO N M EN T S

C++ Android, iOS, Linux, Windows (Win32) x64, Xbox One, Xbox
Series X|S, Switch, PlayStation 4, PlayStation 5, Cocos2D
(community supported)

C# Xamarin and other C#/.NET environments besides Unity

Java Android Studio

JavaScript Phaser.io

Lua Corona (now Solar2D), Defold

NodeJS Node.js applications

Objective-C (community supported) iOS

Photon Facilitates PlayFab integration only

PHP (community supported) PHP

Python (community supported) Python

Unity Titles developed using Unity

Unreal Engine Titles developed using Unreal Engine

By platform/operating system
P L AT F O RM / O P ERAT IN G SY ST EM SDK / L IB RA RY

Android C# (using Xamarin), Java/Android Studio, Lua, Unity, Unreal


Engine

iOS C# (using Xamarin), Lua, Objective-C (community


supported), Unity, Unreal Engine

Linux C++, Lua

PlayStation 4 C++, Unity, Unreal Engine

PlayStation 5 C++, Unity, Unreal Engine

Switch C++, Unity, Unreal Engine

Windows (Win32) x64 C++, Lua, Unity, Unreal Engine

Xbox One, Xbox Series X|S C++, Unity, Unreal Engine

Alternatively, you can also view the available SDKs based on languages, frameworks, game engines, and
scripting languages.

See also
SDKs overview
What is PlayFab?
Android Studio Project (Java)
5/24/2022 • 2 minutes to read • Edit Online

Our Android SDK provides everything you need to access the PlayFab API. This includes models, methods, an
HTTP wrapper for sending and receiving web requests, and JSON serialization.
This SDK is auto-generated using our open-sourced tool—SDKGenerator. We generally build SDKs every other
week to stay current with the latest API changes.

Download links
Android (Java) PlayFab SDK GitHub repo
Quick download link for Android (Java) PlayFab SDK
C#
5/24/2022 • 2 minutes to read • Edit Online

This C# SDK is used in the .NET environment, including Common Language Runtime (CLR). It is frequently used
in cross-platform iOS and Android app titles created using the free, open-source Xamarin platform. This SDK is
also used in games and apps coded in native C# for the Windows platform.
If you have questions about the SDK or need help in resolving issues, go to PlayFab forums > API and SDK .

Download links
C# PlayFab SDK GitHub repo
NuGet package for C# PlayFab SDK
Quick download link for C# PlayFab SDK
This SDK is auto-generated using our open-sourced tool—SDKGenerator. We generally build SDKs every other
week to stay current with the latest API changes.

Key components in this SDK


This C# PlayFab SDK package consists of three different API combinations.
1. PlayFabClientSDK - Contains only client libraries. This is designed for integration on your game client.
2. PlayFabServerSDK - Contains only server and admin APIs. This is designed for integration on your custom
logic server or build process
3. PlayFabSDK - Contains all APIs in one SDK (client, server, and admin), as well as, a unit-test project.

When not to use this SDK


The C# PlayFab SDK should not be used if there is a more specific SDK that is suited for your project.
Specific PlayFab SDK is available for:
Unity PlayFab SDK GitHub repo
For a full list of the different PlayFab SDKs, see Azure PlayFab SDK.

Using the SDK


This native C# project can be used in these two ways.
Admin tools for maintaining your game
Usually, you will want to make synchronous calls back-to-back.
Each API call will lock the program while it's executing, but that's not an issue for this type of program.
See the comment about loginTask.Wait() in the example code below. This is how you'll usually make
API calls.
An actual game coded in native C#
You need to take advantage of the async nature of API calls, and the C# async/await feature keywords.
For more information about asynchronous programming, see Asynchronous Programming with
async and await (C#).

Add SDK to your project


Quickstart to add C# client SDK
Alternatively, you can install the NuGet package into your Visual Studio project using the NuGet Package
Manager. For instructions, see Install and use a package in Visual Studio. For more information, see Getting
started with NuGet.
Quickstart: PlayFab Client library for C#
5/24/2022 • 2 minutes to read • Edit Online

Get started with the PlayFab Client library for C#. Follow steps to install the package and try out example code
for a basic task.
This quickstart helps you make your first PlayFab API call in the using the Client library for C#. Before
continuing, make sure you have completed Getting started for developers, which ensures you have a PlayFab
account and are familiar with the PlayFab Game Manager.
API reference documentation

Requirements
A PlayFab developer account.
An installation of Visual Studio.

CSharp project setup


Installation
1. Open Visual Studio and Select Create a new project .
2. Select Console App (.Net Core) for C#.
3. Install NuGet package for PlayFabAllSDK .

At this point, you should be able to successfully compile the project. The output window should contain
something like the following example.

1>------ Build started: Project: CSharpGettingStarted, Configuration: Debug Any CPU ------
1> CSharpGettingStarted ->
c:\dev\CSharpGettingStarted\CSharpGettingStarted\bin\Debug\CSharpGettingStarted.exe
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

Set up your first API call


This guide provides the minimum steps required to make your first PlayFab API call. Confirmation is done via a
console print.
Your new project should contain a file called Program.cs, which was created automatically by Visual Studio.
Open that file, and replace the contents with the code in the example shown below (after pasting the code, you
may need to refresh the file to see it). Confirmation of the API call will be done using messages written to the
console output.

using System;
using System.Threading;
using System.Threading.Tasks;
using PlayFab;
using PlayFab.ClientModels;

public static class Program


{
private static bool _running = true;
static void Main(string[] args)
{
PlayFabSettings.staticSettings.TitleId = "144"; // Please change this value to your own titleId from
PlayFab Game Manager

var request = new LoginWithCustomIDRequest { CustomId = "GettingStartedGuide", CreateAccount = true


};
var loginTask = PlayFabClientAPI.LoginWithCustomIDAsync(request);
// If you want a synchronous result, you can call loginTask.Wait() - Note, this will halt the
program until the function returns

while (_running)
{
if (loginTask.IsCompleted) // You would probably want a more sophisticated way of tracking
pending async API calls in a real game
{
OnLoginComplete(loginTask);
}

// Presumably this would be your main game loop, doing other things
Thread.Sleep(1);
}

Console.WriteLine("Done! Press any key to close");


Console.ReadKey(); // This halts the program and waits for the user
}

private static void OnLoginComplete(Task<PlayFabResult<LoginResult>> taskResult)


{
var apiError = taskResult.Result.Error;
var apiResult = taskResult.Result.Result;

if (apiError != null)
{
Console.ForegroundColor = ConsoleColor.Red; // Make the error more visible
Console.WriteLine("Something went wrong with your first API call. :(");
Console.WriteLine("Here's some debug information:");
Console.WriteLine(PlayFabUtil.GenerateErrorReport(apiError));
Console.ForegroundColor = ConsoleColor.Gray; // Reset to normal
}
else if (apiResult != null)
{
Console.WriteLine("Congratulations, you made your first successful API call!");
}

_running = false; // Because this is just an example, successful login triggers the end of the
program
}
}
Finish and execute
When you execute this program, following output displays in the consol
"Congratulations, you made your first successful API call! Done! Press any key to close."
At this point, you can start making other API calls, and building your game.
To build Admin utilities, see the alternate source files in the PlayFab CSharpSdk zip file located in
{CSharpSdk}/PlayFabClientSDK/sources .

For a list of all available client API calls, or many other topics, see PlayFab API References.
Java
5/24/2022 • 2 minutes to read • Edit Online

Our Java SDK provides everything you need to access the PlayFab API. This includes models, methods, an HTTP
wrapper for sending and receiving web requests, and JSON serialization. This is the same SDK used in the
Android Project.
This SDK is auto-generated using our open-sourced tool—SDKGenerator. We generally build SDKs every other
week to stay current with the latest API changes.

Download links
Java PlayFab SDK GitHub repo
Quick download link for Java PlayFab SDK

Licenses
Java licenses
Java quickstart for Native and Android Studio
5/24/2022 • 5 minutes to read • Edit Online

This quickstart lets you get up and running with the PlayFab JavaSDK and simple Java program.
Before you can call any PlayFab API, you must have a PlayFab developer account.
The goals for this tutorial are:
Acquire necessary JAR files.
Add JAR files to the classpath.
Create minimal Java console application that executes Custom ID Login API Call.

Acquire necessary JAR files


In order to utilize the PlayFab JavaSDK, we need the PlayFab Client JavaSDK and its dependency, the Google
GSON.
Download the PlayFab Client JavaSDK JAR library here. Look for client-sdk-*.jar , and the corresponding Java
Doc [Optional but useful].
You may download latest Google GSON here. Look for gson-*.jar .

Project Setup with Intellij Idea


Once you have initialized a simple Intellij Idea Java Project, make sure to place the necessary JAR files as shown
in the following example.

The next step is adding JAR files to the classpath. Navigate to File -> , as shown in the example below.
Navigate to Libraries , and add a new Java library as illustrated in the image provided below.

Select the JAR files you added to the libs folder, then select OK as shown below.
If asked for the Module , select the first one in the list. Ensure that all the JAR files were added to the libraries list.

Project Setup with any IDE


The main requirement is to have JAR files added to the classpath. Please consult the guide for your IDE on how
to add JAR files to classpath.

Set up your first API call


Use the code shown below as your main class code.

import java.util.concurrent.*;
import java.util.*;

import com.playfab.PlayFabErrors.*;
import com.playfab.PlayFabSettings;
import com.playfab.PlayFabClientModels;
import com.playfab.PlayFabClientAPI;
public class Main
{
private static boolean _running = true;

public static void main(String[] args) {


PlayFabSettings.TitleId = "144";

PlayFabClientModels.LoginWithCustomIDRequest request = new


PlayFabClientModels.LoginWithCustomIDRequest();
request.CustomId = "GettingStartedGuide";
request.CreateAccount = true;

FutureTask<PlayFabResult<com.playfab.PlayFabClientModels.LoginResult>> loginTask =
PlayFabClientAPI.LoginWithCustomIDAsync(request);
loginTask.run();

while (_running) {
if (loginTask.isDone()) { // You would probably want a more sophisticated way of tracking
pending async API calls in a real game
OnLoginComplete(loginTask);
}

// Presumably this would be your main game loop, doing other things
try {
Thread.sleep(1);
} catch(Exception e) {
System.out.println("Critical error in the example main loop: " + e);
}
}
}

private static void


OnLoginComplete(FutureTask<PlayFabResult<com.playfab.PlayFabClientModels.LoginResult>> loginTask) {
PlayFabResult<com.playfab.PlayFabClientModels.LoginResult> result = null;
try {
result = loginTask.get(); // Wait for the result from the async call
} catch(Exception e) {
System.out.println("Exception in PlayFab api call: " + e); // Did you assign your
PlayFabSettings.TitleId correctly?
}

if (result != null && result.Result != null) {


System.out.println("Congratulations, you made your first successful API call!");
} else if (result != null && result.Error != null) {
System.out.println("Something went wrong with your first API call.");
System.out.println("Here's some debug information:");
System.out.println(CompileErrorsFromResult(result));
}

_running = false; // Because this is just an example, successful login triggers the end of the
program
}

// This is a utility function we haven't put into the core SDK yet. Feel free to use it.
private static <RT> String CompileErrorsFromResult(PlayFabResult<RT> result) {
if (result == null || result.Error == null)
return null;

String errorMessage = "";


if (result.Error.errorMessage != null)
errorMessage += result.Error.errorMessage;
if (result.Error.errorDetails != null)
for (Map.Entry<String, List<String>> pair : result.Error.errorDetails.entrySet() )
for (String msg : pair.getValue())
errorMessage += "\n" + pair.getKey() + ": " + msg;
return errorMessage;
}
}
Finish and Execute
To run the application:
1. Select the play arrow > in the top right corner. This will start program execution, and output panel will
appear.
2. Locate the debug message . This indicates that API call was successful.

At this point, you can start making other API calls, and building your game.
For a list of all available client API calls, see our PlayFab API References documentation.

Deconstruct the code


This optional last section describes every line in GettingStarted.java in detail.
Imports
This is the minimal set of imports used to make PlayFab API calls.
public static void main(String[] args) {
Just a basic loop that kicks off an API call, and waits for it to complete.
PlayFabSettings.TitleId = "xxxx" ;
Every PlayFab developer creates a title in Game Manager. When you publish your game, you
must code that titleId into your game. This lets the client know how to access the correct data
within PlayFab. For most users, just consider it a mandatory step that makes PlayFab work.
PlayFabClientModels.LoginWithCustomIDRequest request = new
PlayFabClientModels.LoginWithCustomIDRequest();
Most PlayFab API methods require input parameters, and those input parameters are
packed into a request object.
Every API method requires a unique request object, with a mix of optional and mandatory
parameters.
For LoginWithCustomIDRequest , there is a mandatory parameter of CustomId , which
uniquely identifies a player and CreateAccount , which allows the creation of a new
account with this call.
For login, most developers will want to use a more appropriate login method.
See the PlayFab Login documentation for a list of all login methods, and input
parameters. Common choices are:
LoginWithAndroidDeviceID
LoginWithIOSDeviceID
LoginWithEmailAddress
FutureTask<PlayFabResult<com.playfab.PlayFabClientModels.LoginResult>> loginTask =
PlayFabClientAPI.LoginWithCustomIDAsync(request)
;
This begins the async request to LoginWithCustomID , using the Java FutureTask framework.
While (running) { if (loginTask.isDone()) { OnLoginComplete(loginTask); } }
Run a trivial main loop, and asynchronously wait for the loginTask to complete.
When finished call OnLoginComplete .
OnLoginComplete (loginTask)

result = loginTask.get() ;
Fetch the async result (this won't cause a block, because we confirmed the FutureTask is already
complete.
if ( result.Result != null ), then the API call was successful.
When successful, the result.Result object of many API callbacks will contain the requested
information.
LoginResult specifically contains some basic information about the player. But for most
users, login is simply a mandatory step before calling other APIs.
If ( result.Error != null ), the API call has failed.
API calls can fail for many reasons, and you should always attempt to handle failure.
Why API calls fail (In order of likelihood)
PlayFabSettings.TitleId is not set. If you forget to set TitleId to your title, then
nothing will work.
Request parameters. If you have not provided the correct or required information for a
particular API call, then it will fail. See error.errorMessage , error.errorDetails , or
error.GenerateErrorReport() for more info.
Device connectivity issue. Cell phones lose/regain connectivity constantly, and so any API
call at any time can fail randomly, and then work immediately after. Going into a tunnel
can disconnect you completely.
PlayFab server issue. As with all software, there can be issues. See our release notes for
updates.
The internet is not 100% reliable. Sometimes the message is corrupted, or fails to reach
the PlayFab server.
If you are having difficulty debugging an issue, and the information within the error information is
not sufficient, please visit us on our forums.
Objective-C (iOS)
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
This is a community supported SDK. Information on this page is no longer maintained and updated.

To learn how you can contribute and provide support for this SDK, refer to the ReadMe at Objective-C PlayFab
SDK repo.
The team at Microsoft would no longer be providing official support for those using this SDK. You can continue
to get community support and updates at PlayFab forums.

NOTE
This topic provides information about the original version of the SDK and does not apply to the newer community
versions.

Our Objective-C SDK provides everything you need to access the PlayFab API. This includes models, methods, an
HTTP wrapper for sending and receiving web requests, and JSON serialization. This SDK allows you to build
native iOS apps in Object-C, and have access to the PlayFab service.

Download links
Objective-C (iOS) PlayFab SDK GitHub repo
Quick download link for Objective-C (iOS) PlayFab SDK
Objective-C quickstart
5/24/2022 • 2 minutes to read • Edit Online

This quickstart assists you in making your first PlayFab API call using Objective-C, by illustrating how to get
started with our Objective-C SDK for native OSX & iOS development.

NOTE
This SDK is currently in Beta, so please let us know if you run into any issues.

Before you can call any PlayFab API, you must have a PlayFab developer account.
Happy Developing!

Getting started
There are two ways to get started:
1. Start with our example implementation project.
2. Import the Objective-C SDK into an existing XCode project.

Configuring PlayFab
Set your PlayFab TitleId in PlayFabSettings.m, on the line:

static NSString * TitleId = @"XXXX";

Set up your first API call


The following code example shows you how to make a PlayFab API request, and receive the response.

//EXAMPLE: Login with custom id request:

//Build the Request object:


ClientLoginWithCustomIDRequest* login_request = [ClientLoginWithCustomIDRequest new];
login_request.CustomId = [[[UIDevice currentDevice] identifierForVendor] UUIDString]; //use the identifier
for vendor as our custom ID.
login_request.CreateAccount = true; //creates a new account if no existing one

//Make each call to [PlayFabClientAPI GetInstance], the first time you do this, an instance will be created
and then used.
[[PlayFabClientAPI GetInstance] LoginWithCustomID:login_request

success:^(LoginResult* result, NSObject* userData) {


//This block will run when we receive successful response, inspect the result class for pertinent
info.
NSLog(@"error %@",result.PlayFabId);
}

failure:^(PlayFabError *error, NSObject *userData) {


//Request errored or failed to connect, inspect the PlayFabError class for pertinent info.
NSLog(@"error %@",error.description);
} withUserData:nil];
Notes
IDFA/advertisingIdentifier logic is present, but has not been properly tested. It is off by default, and is only
available if you explicitly add USE_IDFA=1 to Target > Build Settings > Preprocessor Macros .
testTitleData.json is present in the project, but must be changed to valid data for any Unit Tests to
work.

Troubleshooting
For a complete list of available APIs, see our PlayFab API References documentation.

Contact us
We love to hear from our developer community! Do you have ideas on how we can make our products and
services better?
Our Developer Success Team can assist with answering any questions, as well as process any feedback you have
about PlayFab services.
Forums, Support and Knowledge Base
C++
5/24/2022 • 2 minutes to read • Edit Online

The cross-platform C++ PlayFab SDK provides everything you need to access the PlayFab API. This includes
models, methods, an HTTP wrapper for sending and receiving web requests, and JSON serialization.
If you have questions about the SDK or need help in resolving issues, go to PlayFab forums > API and SDK .

SDK download links


Cross-platform C++ PlayFab SDK GitHub repo
NuGet package for cross-platform C++ SDK
This SDK is auto-generated using our open-sourced tool—SDKGenerator. We generally build SDKs every other
week to stay current with the latest API changes.

Platforms supported by this SDK


Android
iOS
Linux
Windows (Win32) x64
Xbox One
Xbox Series X|S

When not to use this SDK


The cross-platform C++ PlayFab SDK should not be used if there is a more specific SDK that is suited for your
project. Many C++ based engines also integrate Lua.
Specific PlayFab SDK is available for:
Cocos2d-x PlayFab SDK
Unreal Engine PlayFab SDK at Unreal marketplace (external link)
LuaSDK PlayFab SDK
For a full list of the different PlayFab SDKs, see Azure PlayFab SDK.

Using the SDK


This native C++ project can be used in the following ways.
As a stand-alone console Admin tools for maintaining your game.
The cross-platform C++ PlayFab SDK works great for a stand-alone C++ program.
Integrated into an existing Visual Studio based C++ game.
Follow the instructions above to integrate the NuGet Package into your Visual Studio Solution, and
you're ready to go.
Integrated into an existing C++ based game engine.

Add SDK to your project


Quickstart for Android
Quickstart for iOS
Quickstart for Linux
Quickstart for Windows (Win32) x64
Quickstart for Xbox consoles
If none of the above options work for you, you can install the NuGet package into your Visual Studio project
using the NuGet Package Manager. For instructions, see Install and use a package in Visual Studio. For more
information, see Getting started with NuGet.
Quickstart: C++ for Linux
5/24/2022 • 2 minutes to read • Edit Online

Get started with the PlayFab Client library for C++. Follow steps to install the package and try out example code
for a basic task.
This quickstart helps you make your first PlayFab API call in the using the Client library for C++. Before
continuing, make sure you have completed Getting started for developers, which ensures you have a PlayFab
account and are familiar with the PlayFab Game Manager.
This quickstart was written using Ubuntu 18.04 LTS.
API reference documentation | Library source code

Requirements
A PlayFab developer account.

Linux C++ Project Setup


1. Install the following (sudo apt-get install ____ on Ubuntu):
g++
gdb
make
cmake
libjsoncpp-dev
libcurl4-openssl-dev
git-all
2. Clone the PlayFab cross-platform (CPP) SDK into your project folder.
To verify that your installation is correct.
Create a main.cpp and insert the "Hello World" code shown below.

// main.cpp: entry point for the console application

#include <iostream>

int main()
{
std::cout << "Hello World" << std::endl;
return 0;
}

If you're using an IDE, make sure to:


Add the following folders to your sources:
XPlatCppSdk/cppsdk/source/playfab
Add the following folders to your include directories:
XPlatCppSdk/cppsdk
XPlatCppSdk/cppsdk/include
Link the following libraries:
jsoncpp
curl
pthread
Otherwise, create a file named CMakeLists.txt and copy the build commands shown below.

cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD 14)

project(PlayFab_Test)

file(GLOB PF_SOURCE XPlatCppSdk/cppsdk/source/playfab/*.cpp)


add_executable(PlayFab_Test ${PF_SOURCE} main.cpp)

include_directories(XPlatCppSdk/cppsdk)
include_directories(XPlatCppSdk/cppsdk/include)
target_link_libraries(PlayFab_Test -ljsoncpp -lcurl -lpthread)

Build and run the project from inside your IDE, or open a Terminal prompt and run:
cmake .
make
./PlayFab_Test

Set up your first API call


This guide provides the minimum steps to make your first PlayFab API call, without any GUI or on-screen
feedback. Confirmation is performed using a console print statement.
First, replace the contents of main.cpp with the content shown below.
// main.cpp: entry point for the console application

#include "playfab/PlayFabClientDataModels.h"
#include "playfab/PlayFabClientApi.h"
#include "playfab/PlayFabSettings.h"
#include <unistd.h>

using namespace PlayFab;


using namespace ClientModels;

bool finished = false;

void OnLoginSuccess(const LoginResult& result, void* customData)


{
printf("Congratulations, you made your first successful API call!\n");
finished = true;
}

void OnLoginFail(const PlayFabError& error, void* customData)


{
printf("Something went wrong with your first API call.\n");
printf("Here's some debug information:\n");
printf(error.GenerateReport().c_str());
printf("\n");
finished = true;
}

int main()
{
PlayFabSettings::staticSettings->titleId = ("144");

LoginWithCustomIDRequest request;
request.CreateAccount = true;
request.CustomId = "GettingStartedGuide";

PlayFabClientAPI::LoginWithCustomID(request, OnLoginSuccess, OnLoginFail);

while (PlayFabClientAPI::Update() != 0)
sleep(1);

printf("Press enter to exit\n");


getchar();
return 0;
}

Finish and execute


1. Build and run the project inside your IDE, or open Terminal and run:
./PlayFab_Test
2. When it loads, the following text is displayed:
"Congratulations, you made your first successful API call!"
3. Start making other API calls, and build your title.
Quickstart: C++ for Windows
5/24/2022 • 2 minutes to read • Edit Online

Get started with the PlayFab Client library for C++. Follow steps to install the package and try out example code
for a basic task.
This quickstart helps you make your first PlayFab API call in the using the Client library for C++. Before
continuing, make sure you have completed Getting started for developers, which ensures you have a PlayFab
account and are familiar with the PlayFab Game Manager.
API reference documentation | Library source code

Requirements
A PlayFab developer account.
An installation of Visual Studio.

Windows C++ project setup


Installation:
1. Download and install the PlayFab Cross-Platform (CPP) SDK.
2. Create a new C++ Console project.
3. Right-click on the project in Solution Explorer , select Manage NuGet packages , and search using
"playfab". There will be a small number of matches. Select com.playfab.xplatcppsdk .vXXX
4. Verify that your project compiles in x64 Release

Set up your first API call


This guide provides the minimum steps to make your first PlayFab API call, without any GUI or on-screen
feedback. Confirmation is performed using a console print statement.
1. In Visual Studio, open your C++ Console Application.
2. Open the main cpp document for the project. If you did not rename the project, the file name will be similar
to ConsoleApplication1.cpp`.
3. Replace the contents of the file with the code shown below.
// ConsoleApplication1.cpp : Defines the entry point for the console application.
//

#include "playfab/PlayFabError.h"
#include "playfab/PlayFabClientDataModels.h"
#include "playfab/PlayFabClientApi.h"
#include "playfab/PlayFabSettings.h"
#include "playfab/PlayFabApiSettings.h"
#include <windows.h>

using namespace PlayFab;


using namespace ClientModels;

bool finished = false;

void OnLoginSuccess(const LoginResult& result, void* customData)


{
printf("Congratulations, you made your first successful API call!\n");
finished = true;
}

void OnLoginFail(const PlayFabError& error, void* customData)


{
printf("Something went wrong with your first API call.\n");
printf("Here's some debug information:\n");
printf(error.GenerateErrorReport().c_str());
printf("\n");
finished = true;
}

int main()
{
PlayFabSettings::staticSettings->titleId = ("144");

LoginWithCustomIDRequest request;
request.CreateAccount = true;
request.CustomId = "GettingStartedGuide";

PlayFabClientAPI::LoginWithCustomID(request, OnLoginSuccess, OnLoginFail);

while (PlayFabClientAPI::Update() != 0)
Sleep(1);

printf("Press enter to exit\n");


getchar();
return 0;
}

Finish and execute


1. To run the project, select Debug > Star t Debugging .
2. When it loads, the following text is displayed:
"Congratulations, you made your first successful API call!"
3. Start making other API calls, and build your title.
Quickstart: C++ for Xbox
5/24/2022 • 4 minutes to read • Edit Online

Get started with the PlayFab Client library for C++. Follow steps to install the package and try out example code
for a basic task.
This quickstart helps you make your first PlayFab API call in the using the Client library for C++. Before
continuing, make sure you have completed Getting started for developers, which ensures you have a PlayFab
account and are familiar with the PlayFab Game Manager.
API reference documentation | Library source code

Requirements
A PlayFab developer account.
An installation of Visual Studio 2017.
The Xbox SDK is only supported on Visual Studio 2017.

Xbox project setup


Follow the Xbox setup guide for Universal Windows Platform (UWP) applications: UWP on Xbox One. This guide
walks you through setting up your Xbox, the XDK, and Visual Studio to build Xbox applications.

Using the PlayFab CPP SDK


Let's take a look at how to use the PlayFab CPP SDK .

NOTE
The main difference for Xbox is that it has a separate project file for the solution.

Download the latest PlayFab cross-platform (CPP) SDK. Follow the instructions in the README to recursively
clone the dependencies. Note that this SDK is supported across Windows, Linux, and Xbox.
Build the dependencies for Xbox.
1. Open the Xbox One XDK Visual Studio 2017 Command Prompt and run the
build-dependencies-{debug/profile/release}.bat script. This script is located in the build > Xbox folder.
2. We will use debug for now, so make sure you run the debug script.
To build the respective configurations of the external dependencies, run the profile and release scripts. If the
build fails, make sure that you completed a recursive clone of the repo to also clone the external dependencies.
Setting up your Visual Studio project
To help you understand how to set up the project, we use a Direct3D sample for the guide. After you are familiar
with the proper set up procedures, you can choose to start with a different starting sample.
1. Create a new Direct3D sample project by selecting File > New > Project .
2. Under Installed , select Visual C++ > Xbox One > XDK > July 2018 QFE 2 .
NOTE
Based on the XDK you have installed, the version might be different. If you do not see Xbox One under Visual
C++ , re-install the XDK and try again.

3. Select Direct3D 11 Game . Name the project as PlayFabXboxGuide and select enter the location in which
to store the project. To create the project, select OK .
4. To explicitly call out port numbers, edit the package.appxmanifest file. When using ports internally, make
the following change to allow the application to talk to the network:
For more information about using ports internally, see the manifest template code example in the "Xbox
One exclusive resource application network manifest templates" section of Configuring a XIM project in a
manifest.
5. Modify the section for the XML header <mx:Extension Category="windows.xbox.networking"> so that it
looks like what is shown below.

...
<mx:Extension Category="windows.xbox.networking">
<mx:XboxNetworkingManifest>
<mx:SocketDescriptions>
<mx:SocketDescription Name="PlayFabQosApiClient" BoundPort="0" SecureIpProtocol="Udp">
<mx:AllowedUsages>
<mx:SecureDeviceSocketUsage Type="Initiate"/>
<mx:SecureDeviceSocketUsage Type="SendInsecure"/>
<mx:SecureDeviceSocketUsage Type="ReceiveInsecure"/>
</mx:AllowedUsages>
</mx:SocketDescription>
<mx:SocketDescription Name="PlayFabQosApiServer" BoundPort="3075" SecureIpProtocol="Udp">
<mx:AllowedUsages>
<mx:SecureDeviceSocketUsage Type="Accept" />
<mx:SecureDeviceSocketUsage Type="SendInsecure"/>
<mx:SecureDeviceSocketUsage Type="ReceiveInsecure"/>
</mx:AllowedUsages>
</mx:SocketDescription>
</mx:SocketDescriptions>
<mx:SecureDeviceAssociationTemplates>
<mx:SecureDeviceAssociationTemplate Name="PlayFabQosApiTraffic"
InitiatorSocketDescription="PlayFabQosApiClient" AcceptorSocketDescription="PlayFabQosApiServer"
MultiplayerSessionRequirement="None">
<mx:AllowedUsages>
<mx:SecureDeviceAssociationUsage Type="InitiateFromMicrosoftConsole" />
<mx:SecureDeviceAssociationUsage Type="InitiateFromWindowsDesktop" />
<mx:SecureDeviceAssociationUsage Type="AcceptOnOtherDevice" />
</mx:AllowedUsages>
</mx:SecureDeviceAssociationTemplate>
</mx:SecureDeviceAssociationTemplates>
</mx:XboxNetworkingManifest>
</mx:Extension>

To deploy your game:


1. Select F5 to deploy and run the game.
2. Make sure you are connected to your Xbox.
3. On the Xbox One XDK Visual Studio 2017 Command Prompt , run the xbconnect \<xbox ip\>
command to connect to your Xbox.
You should see the game running on your Xbox.
Adding the PlayFab CPP SDK to your project
1. In Visual Studio , right-click on the Solution . Select Add > Existing Project .
2. Navigate to and select XPlatXbox.vcxproj under the build > Xbox folder of the XPlatCppSdk folder.
3. Hit Open . You should now see the XPlatXbox project as part of your solution.
4. Right-click on References under the PlayFabXboxGuide project.
5. Select Add Reference .
6. Under Project > Solution , select the XPlatXbox project and hit OK .
7. Now your project is linked to the XPlatXbox SDK, and you should be able to build to make PlayFab API calls.
Verify that the project builds. Try to build the Solution and make sure you do not have any build errors. If
successful, you are ready to write some code and make your first API call.
Making your first API call
1. Add the PlayFab header file paths to the Additional Include Directories .
2. Right-click on the PlayFabXboxGuide project and select Proper ties .
3. Under Configuration Proper ties > C/C++ > General > Additional Include Directories , add the
path to the code , code\include and external\include folders.
4. Once added, the Additional Include Directories value should look like this:
\<path to the sdk root\>\code; \<path to the sdk root\>\code\include; \<path to the sdk
root\>\external\json\include;%(AdditionalIncludeDirectories)

5. Add a new header file called PlayFabApiCall.h , and add the code shown below to the file.

#pragma once
void MakePlayFabCall();

6. Add a new source file called PlayFabApiCall.cpp with the code shown below.
#include "pch.h"

#include "PlayFabApiCall.h"
#include <playfab/PlayFabClientDataModels.h>
#include <playfab/PlayFabClientApi.h>
#include <playfab/PlayFabSettings.h>
#include <windows.h>

using namespace PlayFab;


using namespace ClientModels;

bool finished = false;

void print_log(const char* format, ...)


{
static char s_printf_buf[1024];
va_list args;
va_start(args, format);
vsnprintf(s_printf_buf, sizeof(s_printf_buf), format, args);
va_end(args);
OutputDebugStringA(s_printf_buf);
}

void OnLoginSuccess(const LoginResult& result, void* customData)


{
print_log("Congratulations, you made your first successful API call!\n");
finished = true;
}

void OnLoginFail(const PlayFabError& error, void* customData)


{
print_log("Something went wrong with your first API call.\n");
print_log("Here's some debug information:\n");
print_log(error.GenerateErrorReport().c_str());
print_log("\n");
finished = true;
}

void MakePlayFabCall()
{
print_log("\n\n=====================Start making your first PlayFab API
call========================\n\n");

PlayFabSettings::titleId = "144";

LoginWithCustomIDRequest request;
request.CreateAccount = true;
request.CustomId = "GettingStartedGuide";

PlayFabClientAPI::LoginWithCustomID(request, OnLoginSuccess, OnLoginFail);

while (PlayFabClientAPI::Update() != 0)
Sleep(1);

print_log("\n============================End your first PlayFab API


call==========================\n\n");
}

Now you have the code to make your first API call.
1. Call the MakePlayFabCall() function in Main.cpp , and add the following include statement:

#include "PlayFabApiCall.h"
2. In the virtualvoid Initialize(CoreApplicationView^ applicationView) function in Main.cpp , add
MakePlayFabCall(); as the last call.
3. Select F5 to deploy and run the application.
4. The result of your first PlayFab API call from the Xbox, displays in the Output log window.
Cocos2D-x (C++)
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
This is a community supported SDK. Information on this page is no longer maintained and updated. This SDK only
supports an old version of Cocos and has not been ported to support the latest version.

To learn how you can contribute and provide support for this SDK, refer to the ReadMe at Cocos2D-x PlayFab
SDK repo.
The team at Microsoft would no longer be providing official support for those using this SDK. You can continue
to get community support and updates at PlayFab forums.

NOTE
This topic provides information about the original version of the SDK and does not apply to the newer community
versions.

Our Cocos2d-x SDK provides everything you need to access the PlayFab API. This includes models, methods, an
HTTP wrapper for sending and receiving web requests, and JSON serialization.
This SDK is auto-generated using the SDKGenerator—an open-sourced tool developed by us. We generally build
SDKs every other week in order to stay current with the latest API changes.
The Cocos SDK has not yet been fully tested across all Cocos platforms - however, this list is improving over
time.
These platforms are tested, and should function very well:
win32
ios_mac
android
These platforms are not tested/working yet:
android-studio
linux
win8.1-universal
win10
Download links
Cocos2D-x PlayFab SDK GitHub repo
Quick download link for Cocos2D-x PlayFab SDK

Licenses
Cocos2D-x licenses
Cocos2D-x quickstart
5/24/2022 • 7 minutes to read • Edit Online

This quickstart assists you in making your first PlayFab API call in the Cocos2d-x engine.
Before you can call any PlayFab API, you must have a PlayFab developer account.

Cocos2d-x project setup


OS: This guide is written for Windows 10, using Visual Studio 2015. Cocos works on most modern OSs and
environments. The installation instructions are similar, but different for each combination.
If you are building for other platforms, the files you need are the same, but you will need to do the project setup
yourself. Visual Studio 2013 will have identical steps, but the screenshots provided here will look a bit different
from yours.
1. Download and install Cocos2d-x
https://www.cocos2d-x.org/download
Setting up Cocos2d-x requires some familiarity. Check out their docs site:
https://docs.cocos2d-x.org/cocos2d-x/en/en/
Note the Cocos Prerequisites
Visual Studio 2013 or 2015 are also required.
2. Once you have Cocos2d-x configured, create a project using the Cocos CLI:
Navigate to a location where you wish to store your Cocos project
Open a command window in your parent folder (Cocos CLI will create the actual project directory)
Hold down your Shift key, and right-click in the empty white space of the Explorer window.

In the new console window enter this command:


cocos new CocosGettingStarted -l cpp
Make sure your target sub-directory (CocosGettingStar ted ) does not already exist -
This command will fail if the folder already exists.
If you get a message that "'cocos' is not recognized as an internal or external command",
you have not configured the cocos installation correctly (Go back to the Cocos windows
installation guide).
If successful, there will be a new folder CocosGettingStar ted . This guide will refer to
that directory location as {CocosGettingStarted} .
Successful output should appear similar to the example provided below.

> Copy template into C:\dev\CocosGettingStarted


> Copying Cocos2d-x files...
> Rename project name from 'HelloCpp' to 'CocosGettingStarted'
> Replace the project name from 'HelloCpp' to 'CocosGettingStarted'
> Replace the project package name from 'org.cocos2dx.hellocpp' to 'org.cocos2dx.CocosGettingStarted'
> Replace the Mac bundle id from 'org.cocos2dx.hellocpp' to 'org.cocos2dx.CocosGettingStarted'
> Replace the iOS bundle id from 'org.cocos2dx.hellocpp' to 'org.cocos2dx.CocosGettingStarted'

3. Download PlayFab Cocos2d-xSdk: Cocos2D-x SDK (C++). Save and extract it to a temporary location
{PlayFabCocos}
Open the following folder in Windows Explorer: {PlayFabCocos}/PlayFabClientSDK
Open the following folder in a second Windows Explorer: {CocosGettingStarted}/Classes
4. Copy paste all files from {PlayFabCocos}/PlayFabClientSDK to {CocosGettingStarted}/Classes
5. In Visual Studio, Load {CocosGettingStarted}/proj.win32/CocosGettingStarted.sln .
6. We want to add the PlayFab files to the Cocos project.
7. In Visual Studio, Solution Explorer panel, expand to the folder: Solution/CocosGettingStarted/src
8. Open a Windows Explorer window at {CocosGettingStarted}/Classes
Select all files in {CocosGettingStarted}/Classes, EXCEPT AppDelegate.h, AppDelegate.cpp,
HelloWorldScene.h, HelloWorldScene.cpp
Drag and drop all of those files from Explorer, onto the Visual Studio
Solution/CocosGettingStarted/src folder we found above. If you experience problems, you can
drag and drop each file one at a time, just be careful and get all of them.
You should see these files in your VS project:

PlayFab uses several Cocos libraries that have to be manually added to the dependencies list.
Open the Proper ties window for your CocosGettingStarted project (as shown below).

Replace the Additional Include Directories with this:


$(ProjectDir)..\cocos2d\external\zlib\include;$(ProjectDir)..\cocos2d\external\curl\include\win32;$(EngineRoot)cocos\audio\include;$(EngineRoot)external;$(EngineRoot)e
(AdditionalIncludeDirectories);$(_COCOS_HEADER_WIN32_BEGIN);$(_COCOS_HEADER_WIN32_END);..\cocos2d

NOTE
We are adding curl and zlib, which are libraries that come with Cocos, but are not enabled by default.

Your CocosGettingStarted project should now compile (and even run), but we are not yet making any PlayFab
API calls.
Installation complete!

Set up your first API call


This guide provides the minimum steps to make your first PlayFab API call. Confirmation is visible in the app.
1. In Visual Studio, inside of the Solution/CocosGettingStarted/src folder, Open HelloWorldScene.h and replace
the contents with this:
In Visual Studio, inside of the Solution/CocosGettingStar ted/src folder, Open HelloWorldScene.h
and replace the contents with those shown below.
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"
#include "PlayFabClientDataModels.h"
#include "PlayFabError.h"

class HelloWorld : public cocos2d::Layer


{
public:
static std::string statusMsg;
static cocos2d::Scene* createScene();
static cocos2d::Label* testReportLabel;
virtual bool init();
void update(float) override;
void menuCloseCallback(cocos2d::Ref* pSender);
CREATE_FUNC(HelloWorld);

static void HelloWorld::OnLoginSuccess(const PlayFab::ClientModels::LoginResult& result, void*


customData);
static void HelloWorld::OnLoginFail(const PlayFab::PlayFabError& error, void* customData);
};

#endif // __HELLOWORLD_SCENE_H__

2. Immediately next to that, open HelloWorldScene.cpp , and replace the contents with this:

#include "HelloWorldScene.h"
#include "PlayFabClientAPI.h"
#include <PlayFabSettings.h>

USING_NS_CC;

std::string HelloWorld::statusMsg;
cocos2d::Label* HelloWorld::testReportLabel;

Scene* HelloWorld::createScene()
{
auto scene = Scene::create(); // 'scene' is an autorelease object
auto layer = HelloWorld::create(); // 'layer' is an autorelease object
scene->addChild(layer); // add layer as a child to scene
return scene; // return the scene
}

bool HelloWorld::init()
{
if (!Layer::init())
return false;

Size visibleSize = Director::getInstance()->getVisibleSize();


Vec2 origin = Director::getInstance()->getVisibleOrigin();

auto closeItem = MenuItemImage::create("CloseNormal.png", "CloseSelected.png",


CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width / 2,
origin.y + closeItem->getContentSize().height / 2));

auto menu = Menu::create(closeItem, NULL);


menu->setPosition(Vec2::ZERO);
this->addChild(menu, 1);
this->scheduleUpdate();

testReportLabel = Label::createWithTTF("", "fonts/Marker Felt.ttf", 14);


this->addChild(testReportLabel, 1);

statusMsg = "Login pending...";


PlayFab::PlayFabSettings::titleId = "144";
PlayFab::ClientModels::LoginWithCustomIDRequest request;
request.CustomId = "GettingStartedGuide";
request.CreateAccount = true;
PlayFab::PlayFabClientAPI::LoginWithCustomID(request, OnLoginSuccess, OnLoginFail, nullptr);

return true;
}

void HelloWorld::menuCloseCallback(Ref* pSender)


{
Director::getInstance()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit(0);
#endif
}

void HelloWorld::update(float delta)


{
Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();

testReportLabel->setPosition(Vec2(origin.x + visibleSize.width / 2, origin.y + visibleSize.height / 2));


testReportLabel->setString(statusMsg);
}

void HelloWorld::OnLoginSuccess(const PlayFab::ClientModels::LoginResult& result, void* customData)


{
statusMsg = "Congratulations, you made your first successful API call!";
}

void HelloWorld::OnLoginFail(const PlayFab::PlayFabError& error, void* customData)


{
statusMsg = "Something went wrong with your first API call.\n";
statusMsg += "Here's some debug information:\n";
statusMsg += error.GenerateErrorReport();
}

These files take the existing HelloWorldScene that is part of the new-Cocos-project template, and modify them
to include your first PlayFab API call.

Finish and execute


1. Build and Execute your Cocos Project: Dropdowns -> Debug -> Start Debugging.
2. This may prompt you to build. Select Yes .
3. You should see a screen that says:
Congratulations, you made your first successful API call!
4. Now, you can start making other api calls, and building your game.
For a list of all available client API calls, see our PlayFab API References documentation.
Happy coding!

Deconstruct the code


This optional last section describes each part of source code above, in detail.
HelloWorldScene.h

This is only trivially modified from the default HelloWorldScene.h generated by Cocos.
Specifically, it defines some Cocos GUI we are using, and the prototype for OnLoginSuccess and
OnLoginFail .
Everything else is just standard Cocos Engine functions.
HelloWorldScene.cpp

createScene() is a standard Cocos Engine function.


init()

Normal Cocos Gui stuff: closeItem and testReportLabel .


PlayFab::PlayFabSettings::titleId = "xxxx";

Every PlayFab developer creates a title in Game Manager. When you publish your game,
you must code that titleId into your game. This lets the client know how to access the
correct data within PlayFab. For most users, just consider it a mandatory step that makes
PlayFab work.
PlayFab::ClientModels::LoginWithCustomIDRequest request;

Most PlayFab API methods require input parameters, and those input parameters are
packed into a request object.
Every API method requires a unique request object, with a mix of optional and
mandatory parameters.
For LoginWithCustomIDRequest , there is a mandatory parameter of CustomId ,
which uniquely identifies a player and CreateAccount , which allows the creation
of a new account with this call.
For login, most developers will want to use a more appropriate login method.
See the PlayFab Login documentation for a list of all login methods, and input
parameters. Common choices are:
LoginWithAndroidDeviceID
LoginWithIOSDeviceID
LoginWithEmailAddress
PlayFab::PlayFabClientAPI::LoginWithCustomID(request, OnLoginSuccess, OnLoginFail,
nullptr);

This begins the async request to LoginWithCustomID , and will invoke the OnLoginSuccess
or OnLoginFail function when complete.
update(float delta)

Simply setting the statusMsg variable does not update the on-screen text.
This function sets the GUI text to match the contents of statusMsg every tick (not very
efficient).
OnLoginSuccess(result, customData)

When the success callback is called, the result object of many API callbacks will contain the
requested information.
LoginResult contains some basic information about the player, but for most users, login is
simply a mandatory step before calling other APIs.
OnLoginFail(error, customData)

If the error-function is called, your API call has failed.


API calls can fail for many reasons, and you should always attempt to handle failure.
Why API calls fail (In order of likelihood)
PlayFabSettings.TitleId is not set. If you forget to set titleId to your title, then nothing
will work.
In Cocos, the curl library will probably just crash your game if you fail to set titleId
correctly.
Request parameters. If you have not provided the correct or required information for a
particular API call, then it will fail. See error.errorMessage , error.errorDetails , or
error.GenerateErrorReport() for more info.
Device connectivity issue. Cell phones lose/regain connectivity constantly, and so any API
call at any time can fail randomly, and then work immediately after. Going into a tunnel
can disconnect you completely.
PlayFab server issue. As with all software, there can be issues. See our release notes for
updates.
The internet is not 100% reliable. Sometimes the message is corrupted or fails to reach
the PlayFab server.
If you are having difficulty debugging an issue, and the information within the error callback is
not sufficient, please visit us on our forums.
customData is a void-pointer which can be used in any way to establish context.
In C++, it is harder to maintain the context of an API call, so we added the customData
parameter, which can relay any object to the callback, which can be used however you like to
establish context.
Thus, if you make API calls to retrieve inventory, you can pass a player, or inventory pointer as
customData , and update the inventory on that object, in the callback.
Phaser SDK (Javascript)
5/24/2022 • 2 minutes to read • Edit Online

Our JavaScript SDK is fully compatible with Phaser.io, and provides everything you need to access the PlayFab
API.
This SDK is auto-generated using our open-sourced tool—SDKGenerator. We generally build SDKs every other
week to stay current with the latest API changes.
This SDK can alternatively be obtained via our CDN. Additional details can be found here.

Download links
Phaser (JavaScript) PlayFab SDK GitHub repo
Quick download link for Phaser (JavaScript) PlayFab SDK
Photon
5/24/2022 • 2 minutes to read • Edit Online

This section provides info about using PlayFab together with Photon multiplayer services such as Photon
RealTime and Photon Unity Networking (PUN).
Currently, we offer the following Photon integrations:
Authenticate Photon players with PlayFab.
Listen for room events using PlayFab CloudScript callbacks.
Photon quickstart
5/24/2022 • 17 minutes to read • Edit Online

This quickstart shows how to set up Photon Multiplayer to work with PlayFab. Currently, PlayFab offers the
following Photon integrations:
Authenticate Photon players with PlayFab.
Listen for room events using PlayFab CloudScript callbacks.
In this quickstart, we will illustrate how both features work using the latest Photon Unity example project.

Prerequisites
1. A Unity project with the PlayFab SDK imported, and a configured title.
2. The PlayFab title registered.

NOTE
This guide omits the Chat Application settings. For your Chat Application to be integrated, create a new Photon Chat
Application, and enter the App ID in the corresponding boxes in Unity and in the PlayFab Game Manager - Photon Add-
on page.

Setting up a Photon application


1. Once you have registered and logged into the Photon dashboard, select Create a new App , as shown in the
example provided below.

In the example shown below:


1. Select Photon Type .
2. Choose a Name .
3. Create a Description .
4. Submit by selecting Create .
Setting up authentication
1. Find the newly created Application in the list, and select Manage , as shown in the example below.

The Application dashboard will open.


1. Find and save the App ID located under the page Title , as shown below.

1. Locate the Authentication section.


2. Select the Custom Ser ver , as shown in the selection provided below.
The next page will let you configure the Authentication URL for Photon. The format is shown below.

https://{PlayFabTitleId}.playfabapi.com/photon/authenticate

Replace the Title Id place holder with your own Title Id.

{PlayFabTitleId}

1. Enter the URL .


2. Submit by selecting the Create button, as shown below.

Setting up a PlayFab title for Photon


Navigate to your title's Game Manager page, then:
1. Navigate to Add-ons tab.
2. In the list of Add-ons , find and select Photon .
1. The Photon Add-on page will allow you to install Photon by specifying your Photon Realtime
Application ID .
Optionally, you may specify Chat App ID .
Once you install the Add-on (3) , a Photon secret Key will be generated (2) .
Save it for future use when configuring web-hooks.

NOTE
Remember to save your Photon secret key in a safe and easily accessible place. It will come in handy when configuring
Webhooks.

Setting Photon webhooks


As an optional integration, Photon may transmit certain events to your PlayFab CloudScript. This is done by
means of webhooks:
You specify a Base URL.
Then you specify path for each of the available Events.
A path is, effectively, a handler name implemented in your CloudScript.
The base URL will have the following format:

https://{PlayFabTitleId}.playfablogic.com/webhook/1/prod/{PhotonSecretKey}

Make sure to replace Title Id placeholder with your own Title Id.

{PlayFabTitleId}

Make sure to replace the PhotonSecretKey token with the Secret Key you generated on the Photon Add-on
page.

{PhotonSecretKey}

1. Fill in the Base URL .


2. Assign a CloudScript handler Name for each of the available Events .
3. Remove any CustomHttpHeaders .
4. Submit this by selecting the Save button.

Setting up a Unity project


The guide assumes you already have PlayFab SDK imported, set up, and the title setting configured.
Start by navigating to the Asset Store .
Locate Photon Unity Networking Free package.
Select Impor t (1) .
You may inspect the imported files.
Then select Impor t (2) .

Right after import process finishes, the PUN Setup window will open.
Enter your Realtime Application ID (1) found in the Photon Application Dashboard for the Photon
App you created.
Select Setup Project (2) .
Once the setup finishes, select Close (3) .
If AppId was accepted, the Photon Ser ver Settings object will be selected and viewable in the Unity
Inspector window. To manually access the Ser ver Settings object:
Navigate to the top window panel.
Select Window .
Then select Photon Unity Networking (1) .
Finally select Highlight Ser ver Settings (2) .
The Standard Unity project window will reveal the PhotonSer verSettings (3) object.
Select the object to reveal its settings in the Unity Inspector window.
NOTE
As part of PhotonSer verSettings , you have the option to assign the Chat Application ID .

At this point the project is configured.

Implementing PlayFab to Photon authentication


When you enable the Photon Add-on for your title in the PlayFab Game Manager, and configure the
authentication on the Photon Application dashboard, PlayFab allows you to authenticate existing PlayFab
players inside the Photon environment.
This means you may completely avoid implementing any user management for Photon.
1. Navigate to DemoHub-Scene-V2 scene from the Photon Unity Networking Free package, the Classic
version.
This scene is a hub for all the examples from the package.
As it is the first scene to load, let's add a small script to enable authenticating PlayFab with Photon.
2. Create an empty GameObject called PlayFabAuthenticator .
3. Then in the Unity Inspector window, add a component with the same name to this GameObject .
Select the gear icon, then choose to edit the script from the drop-down menu. Copy and paste the code for the
PlayFabAuthenticator component as illustrated below (please, read the comments for the explanation), and save
and close the file.

using PlayFab;
using PlayFab.ClientModels;
using UnityEngine;

public class PlayFabAuthenticator : MonoBehaviour {

private string _playFabPlayerIdCache;

//Run the entire thing on awake


public void Awake() {
AuthenticateWithPlayFab();
}

/*
* Step 1
* We authenticate current PlayFab user normally.
* In this case we use LoginWithCustomID API call for simplicity.
* You can absolutely use any Login method you want.
* We use PlayFabSettings.DeviceUniqueIdentifier as our custom ID.
* We pass RequestPhotonToken as a callback to be our next step, if
* authentication was successful.
*/
private void AuthenticateWithPlayFab(){
LogMessage("PlayFab authenticating using Custom ID...");

PlayFabClientAPI.LoginWithCustomID(new LoginWithCustomIDRequest()
{
CreateAccount = true,
CustomId = PlayFabSettings.DeviceUniqueIdentifier
}, RequestPhotonToken, OnPlayFabError);
}

/*
* Step 2
* We request Photon authentication token from PlayFab.
* This is a crucial step, because Photon uses different authentication tokens
* than PlayFab. Thus, you cannot directly use PlayFab SessionTicket and
* you need to explicitly request a token. This API call requires you to
* pass Photon App ID. App ID may be hard coded, but, in this example,
* We are accessing it using convenient static field on PhotonNetwork class
* We pass in AuthenticateWithPhoton as a callback to be our next step, if
* we have acquired token successfully
*/
private void RequestPhotonToken(LoginResult obj) {
LogMessage("PlayFab authenticated. Requesting photon token...");
//We can player PlayFabId. This will come in handy during next step
_playFabPlayerIdCache = obj.PlayFabId;

PlayFabClientAPI.GetPhotonAuthenticationToken(new GetPhotonAuthenticationTokenRequest()
PlayFabClientAPI.GetPhotonAuthenticationToken(new GetPhotonAuthenticationTokenRequest()
{
PhotonApplicationId = PhotonNetwork.PhotonServerSettings.AppID
}, AuthenticateWithPhoton, OnPlayFabError);
}

/*
* Step 3
* This is the final and the simplest step. We create new AuthenticationValues instance.
* This class describes how to authenticate a players inside Photon environment.
*/
private void AuthenticateWithPhoton(GetPhotonAuthenticationTokenResult obj) {
LogMessage("Photon token acquired: " + obj.PhotonCustomAuthenticationToken + " Authentication
complete.");

//We set AuthType to custom, meaning we bring our own, PlayFab authentication procedure.
var customAuth = new AuthenticationValues { AuthType = CustomAuthenticationType.Custom };
//We add "username" parameter. Do not let it confuse you: PlayFab is expecting this parameter to
contain player PlayFab ID (!) and not username.
customAuth.AddAuthParameter("username", _playFabPlayerIdCache); // expected by PlayFab custom
auth service

//We add "token" parameter. PlayFab expects it to contain Photon Authentication Token issues to your
during previous step.
customAuth.AddAuthParameter("token", obj.PhotonCustomAuthenticationToken);

//We finally tell Photon to use this authentication parameters throughout the entire application.
PhotonNetwork.AuthValues = customAuth;
}

private void OnPlayFabError(PlayFabError obj) {


LogMessage(obj.GenerateErrorReport());
}

public void LogMessage(string message) {


Debug.Log("PlayFab + Photon Example: " + message);
}
}

Testing PlayFab to Photon authentication


1. Start the scene, as shown in the example provided below.
2. Inspect the flow of console messages. Control that:
3. Authentication to PlayFab itself was successful.
4. The Photon token was acquired.
The following picture illustrates the correct flow.
Once the Photon token has been acquired, and authentication is complete, we are okay to check out the Photon
demos.
For example, start a demo called Demo Boxes .
1. To ensure that the PlayFab authentication is complete, select Demo Boxes .
2. Then select Load Demo , as shown on the following picture.

Photon will start outputting debug messages. By simply monitoring your console, you can easily spot if you
have any authentication issues.
Ensure that no Authentication Denied errors are present in the console. At this point, you have set up minimal
PlayFab and Photon integration.

Photon room event + CloudScript


The Photon matchmaking system has the concept of a Room. If you are not familiar with this concept, please
consult with the Photon Matchmaking Guide.
PlayFab allows you to intercept various room events. The following room events require only CloudScript to be
intercepted:
RoomCreated
RoomJoined
RoomLeft
RoomClosed

The following events will require additional control over Unity code to be intercepted (details are given later in
this document):
RoomPropertyUpdated
RoomEventRaised

NOTE
Once you introduce a handler for a room event, it becomes an essential part of the event handling flow. So errors
produced while running your CloudScript may cause problems for the entire system. For example, if the RoomCreated
handler throws an error, your clients will throw an error as well, and will not be able to connect properly.

Let's construct a PlayFab CloudScript by defining a handler for each event type individually.
Room Created handler
The RoomCreated handler is invoked every time a Photon room is created. The following CloudScript handler
will intercept such event.

// Triggered automatically when a Photon room is first created


handlers.RoomCreated = function (args) {
return { ResultCode : 0, Message: 'Success' };
};

NOTE
You may acquire additional data about the event using the "args" argument. The example of args payload is given below.
{
"ActorNr": 1,
"AppVersion": "1.2_1.85",
"AppId": "bfd5f98b-c6a4-4763-80d9-824d20db842b",
// Options with which the room was created.
"CreateOptions": {
"MaxPlayers": 4,
"LobbyId": null,
"LobbyType": 0,
"CustomProperties": {

},
"EmptyRoomTTL": 0,
"PlayerTTL": 0,
"CheckUserOnJoin": false,
"DeleteCacheOnLeave": true,
"SuppressRoomEvents": false,
"PublishUserId": false,
"ExpectedUsers": null
},
// Unique game identifier
"GameId": "8b8322de-096d-4481-a2b2-8db8bb45cfef",
"Region": "EU",
"Type": "Create",
// User that caused the room to be created
"UserId": "834D5AA5BAB1DFB6",
"Username": ""
}

Room Joined handler


The RoomJoined handler is invoked every time a player joins the room. The following CloudScript handler will
intercept such an event.

// Triggered automatically when a player joins a Photon room


handlers.RoomJoined = function (args) {
return { ResultCode : 0, Message: 'Success' };
};

This callback is not invoked for the very first user entering the room. Use RoomCreated to intercept the first
player that joins. You may acquire additional data about the event using the "args" argument.
The example of args payload is shown below.

{
"ActorNr": 2,
"AppVersion": "1.2_1.85",
"AppId": "bfd5f98b-c6a4-4763-80d9-824d20db842b",
// Unique Game Identifier
"GameId": "b0f55a2e-431d-402a-9809-b0240443267e",
"Region": "EU",
"Type": "Join",
// Id of the player that has joined
"UserId": "AAC7634BF46289DF",
"Username": ""
}

Room left
The RoomLeft handler is invoked every time a player leaves the room. The following CloudScript handler will
intercept such event.
// Triggered automatically when a player leaves a Photon room
handlers.RoomLeft = function (args) {
return { ResultCode : 0, Message: 'Success' };
};

You may acquire additional data about the event using "args" argument. The example of args payload is shown
below.

{
"ActorNr": 2,
"AppVersion": "1.2_1.85",
"AppId": "bfd5f98b-c6a4-4763-80d9-824d20db842b",
// Unique Game Identifier
"GameId": "b0f55a2e-431d-402a-9809-b0240443267e",
"IsInactive": false,
"Reason": "0",
"Region": "EU",
"Type": "ClientDisconnect",
// Id of the user that has left the room
"UserId": "AAC7634BF46289DF",
"Username": ""
}

Room Closed handler


The RoomClosed handler is invoked every time the last player leaves the room and room has no players left. The
following CloudScript handler will intercept such event.

// Triggered automatically when a Photon room closes


// Note: currentPlayerId is undefined in this function
handlers.RoomClosed = function (args) {
return { ResultCode : 0, Message: 'Success' };
};

You may acquire additional data about the event using "args" argument. The example of args payload is shown
below.

"ActorCount": 0,
"ActorNr": 1,
"AppVersion": "1.2_1.85",
"AppId": "bfd5f98b-c6a4-4763-80d9-824d20db842b",
// Unique game identifier
"GameId": "b0f55a2e-431d-402a-9809-b0240443267e",
"Region": "EU",
"State2": {
"ActorList": [

]
},
"Type": "Close"
}

Room Property Updated


The RoomPropertyUpdated handler is invoked every time the room property is changed. The following
CloudScript handler will intercept such an event.
// Triggered automatically when a Photon room game property is updated.
// Note: currentPlayerId is undefined in this function
handlers.RoomPropertyUpdated = function (args) {
return { ResultCode : 0, Message: 'Success' };
};

NOTE
The currentPlayerId is undefined in this handler. If the room property was changed from the client, you may use the
"args" argument, and refer to the UserId to acquire the player in charge.

You may acquire additional data about the event using "args" argument. The example of args payload is shown
below.

{
"ActorNr": 1,
"AppVersion": "1.2_1.85",
"AppId": "bfd5f98b-c6a4-4763-80d9-824d20db842b",
// Custom Room Properties
"Properties": {
"CustomProperty": "It's Value"
},
"GameId": "8b8322de-096d-4481-a2b2-8db8bb45cfef",
"Region": "EU",
"State": {
"ActorCounter": 1,
"ActorList": [
{
"ActorNr": 1,
"UserId": "834D5AA5BAB1DFB6",
"Username": "",
"IsActive": true,
"Binary": "RGIAAAEBRAAAAAFi\/3MAAA==",
"DEBUG_BINARY": {
"1": {
"255": ""
}
}
}
],
"Binary": {
"18":
"RAAAAANi+nkAAHNzAA1QbGF5ZXJJbmRleGVzRGlpAAEAAAABAAAAAHMADkN1c3RvbVByb3BlcnR5cwAKSXQncyBWYWx1ZQ=="
},
"CheckUserOnJoin": false,
"CustomProperties": {

},
"DeleteCacheOnLeave": true,
"EmptyRoomTTL": 0,
"IsOpen": true,
"IsVisible": true,
"LobbyType": 0,
"LobbyProperties": [

],
"MaxPlayers": 4,
"PlayerTTL": 0,
"SuppressRoomEvents": false,
"Slice": 0,
"DebugInfo": {
"DEBUG_PROPERTIES_18": {
"250": [
],
"PlayerIndexes": {
"1": 0
},
"CustomProperty": "It's Value"
}
},
"ExcludedActors": [

],
"PublishUserId": false,
"ExpectedUsers": [

]
},
"Type": "Game",
"UserId": "834D5AA5BAB1DFB6",
"Username": ""
}

When changing custom Room properties using the Unity Photon client, it is important to mark the call, so that it
passes the event to Webhook (PlayFab in this case).

// Properties updates ( this hashtable contains the properties to be changed. Properties not mentioned here
will stay as is
var properties = new ExitGames.Client.Photon.Hashtable() { { "CustomProperty" , "It's Value" } };

// Control set. Empty in this case, because our property has not existed before.
// Otherwise you would include previous value of the property.
var expectedProperties = new ExitGames.Client.Photon.Hashtable();

// Set Custom Properties call. Notice the last argument set to "true"
// This tells Photon to forward event to the webhook.
PhotonNetwork.room.SetCustomProperties(properties, expectedProperties, true);

Room Event Raised


The Room Event Raised is called every time a custom room event is raised. The following CloudScript
handler will intercept such an event.

// Triggered by calling "OpRaiseEvent" on the Photon client. The "args.Data" property is


// set to the value of the "customEventContent" HashTable parameter, so you can use
// it to pass in arbitrary data.
handlers.RoomEventRaised= function (args) {
return { ResultCode : 0, Message: 'Success' };
};

You may acquire additional data about the event using "args" argument. The example of args payload is shown
below.

{
"ActorNr": 1,
"AppVersion": "1.2_1.85",
"AppId": "bfd5f98b-c6a4-4763-80d9-824d20db842b",
// Custom event data
"Data": {
"Hello": "World"
},
"GameId": "8b8322de-096d-4481-a2b2-8db8bb45cfef",
"Region": "EU",
"State": {
"ActorCounter": 1,
"ActorList": [
"ActorList": [
{
"ActorNr": 1,
"UserId": "834D5AA5BAB1DFB6",
"Username": "",
"IsActive": true,
"Binary": "RGIAAAEBRAAAAAFi\/3MAAA==",
"DEBUG_BINARY": {
"1": {
"255": ""
}
}
}
],
"Binary": {
"18": "RAAAAAJi+nkAAHNzAA1QbGF5ZXJJbmRleGVzRGlpAAEAAAABAAAAAA=="
},
"CheckUserOnJoin": false,
"CustomProperties": {

},
"DeleteCacheOnLeave": true,
"EmptyRoomTTL": 0,
"IsOpen": true,
"IsVisible": true,
"LobbyType": 0,
"LobbyProperties": [

],
"MaxPlayers": 4,
"PlayerTTL": 0,
"SuppressRoomEvents": false,
"Slice": 0,
"DebugInfo": {
"DEBUG_PROPERTIES_18": {
"250": [

],
"PlayerIndexes": {
"1": 0
}
}
},
"ExcludedActors": [

],
"PublishUserId": false,
"ExpectedUsers": [

]
},
"Type": "Event",
// PlayFab User Id if he/she was the source of the event
"UserId": "834D5AA5BAB1DFB6",
"Username": "",
// Event code
"EvCode": 15
}

When raising custom room events using Unity Photon client, it is important to mark the call so that it passes the
event to Webhooks (PlayFab in this case).
var data = new Dictionary<string,object>() {
{ "Hello" , "World" }
};

// Raise custom room event


// Replace 15 with any custom event code of your choice [0..299]
PhotonNetwork.RaiseEvent(15, data, true, new RaiseEventOptions() {
ForwardToWebhook = true, // Mark call to pass event to Webhook (PlayFab in this case)
});

Testing Room Event handlers


This example extends the previous example (PlayFab + Photon authentication).
Upload the following CloudScript for your title.

handlers.RoomCreated = function (args) {


server.WriteTitleEvent({
EventName : "room_created"
});
return { ResultCode : 0, Message: 'Success' };
};

handlers.RoomJoined = function (args) {


server.WriteTitleEvent({
EventName : "room_joined"
});
return { ResultCode : 0, Message: 'Success' };
};

handlers.RoomLeft = function (args) {


server.WriteTitleEvent({
EventName : "room_left"
});
return { ResultCode : 0, Message: 'Success' };
};

handlers.RoomClosed = function (args) {


server.WriteTitleEvent({
EventName : "room_closed"
});
return { ResultCode : 0, Message: 'Success' };
};

handlers.RoomPropertyUpdated = function (args) {


server.WriteTitleEvent({
EventName : "room_property_changed"
});
return { ResultCode : 0, Message: 'Success' };
};

handlers.RoomEventRaised = function (args) {


server.WriteTitleEvent({
EventName : "room_event_raised"
});
return { ResultCode : 0, Message: 'Success' };
};

The code does nothing more than posting a new title event whenever a Photon callback is invoked. Being of no
use in production, this example will let us clearly see how the callbacks are invoked.
Extend the PlayFabAuthenticator script by including new example code that will raise custom event, and set
custom room property. The extended version also utilizes an Awake method to not destroy object between
scene loads.

using System.Collections.Generic;
using PlayFab;
using PlayFab.ClientModels;
using UnityEngine;

public class PlayFabAuthenticator : MonoBehaviour {

private string _playFabPlayerIdCache;

//Run the entire thing on awake


public void Awake() {
AuthenticateWithPlayFab();
DontDestroyOnLoad(gameObject);
}

/*
* Step 1
* We authenticate current PlayFab user normally.
* In this case we use LoginWithCustomID API call for simplicity.
* You can absolutely use any Login method you want.
* We use PlayFabSettings.DeviceUniqueIdentifier as our custom ID.
* We pass RequestPhotonToken as a callback to be our next step, if
* authentication was successful.
*/
private void AuthenticateWithPlayFab() {
LogMessage("PlayFab authenticating using Custom ID...");

PlayFabClientAPI.LoginWithCustomID(new LoginWithCustomIDRequest()
{
CreateAccount = true,
CustomId = PlayFabSettings.DeviceUniqueIdentifier+"EDITOR"
}, RequestPhotonToken, OnPlayFabError);
}

/*
* Step 2
* We request Photon authentication token from PlayFab.
* This is a crucial step, because Photon uses different authentication tokens
* than PlayFab. Thus, you cannot directly use PlayFab SessionTicket and
* you need to explicitly request a token. This API call requires you to
* pass Photon App ID. App ID may be hard coded, but, in this example,
* We are accessing it using convenient static field on PhotonNetwork class
* We pass in AuthenticateWithPhoton as a callback to be our next step, if
* we have acquired token successfully
*/
private void RequestPhotonToken(LoginResult obj) {
LogMessage("PlayFab authenticated. Requesting photon token...");

//We can player PlayFabId. This will come in handy during next step
_playFabPlayerIdCache = obj.PlayFabId;

PlayFabClientAPI.GetPhotonAuthenticationToken(new GetPhotonAuthenticationTokenRequest()
{
PhotonApplicationId = PhotonNetwork.PhotonServerSettings.AppID
}, AuthenticateWithPhoton, OnPlayFabError);
}

/*
* Step 3
* This is the final and the simplest step. We create new AuthenticationValues instance.
* This class describes how to authenticate a players inside Photon environment.
*/
private void AuthenticateWithPhoton(GetPhotonAuthenticationTokenResult obj) {
LogMessage("Photon token acquired: " + obj.PhotonCustomAuthenticationToken + " Authentication
LogMessage("Photon token acquired: " + obj.PhotonCustomAuthenticationToken + " Authentication
complete.");

//We set AuthType to custom, meaning we bring our own, PlayFab authentication procedure.
var customAuth = new AuthenticationValues { AuthType = CustomAuthenticationType.Custom };

//We add "username" parameter. Do not let it confuse you: PlayFab is expecting this parameter to
contain player PlayFab ID (!) and not username.
customAuth.AddAuthParameter("username", _playFabPlayerIdCache); // expected by PlayFab custom
auth service

//We add "token" parameter. PlayFab expects it to contain Photon Authentication Token issues to your
during previous step.
customAuth.AddAuthParameter("token", obj.PhotonCustomAuthenticationToken);

//We finally tell Photon to use this authentication parameters throughout the entire application.
PhotonNetwork.AuthValues = customAuth;
}

private void OnPlayFabError(PlayFabError obj) {


LogMessage(obj.ErrorMessage);
}

public void LogMessage(string message) {


Debug.Log("PlayFab + Photon Example: " + message);
}

// Add small button to launch our example code


public void OnGUI() {
if (GUILayout.Button("Execute Example ")) ExecuteExample();
}

// Example code which raises custom room event, then sets custom room property
private void ExecuteExample() {

// Raise custom room event


var data = new Dictionary<string, object>() { {"Hello","World"} };
var result = PhotonNetwork.RaiseEvent(15, data, true, new RaiseEventOptions()
{
ForwardToWebhook = true,
});
LogMessage("New Room Event Post: "+result);

// Set custom room property


var properties = new ExitGames.Client.Photon.Hashtable() { { "CustomProperty", "It's Value" } };
var expectedProperties = new ExitGames.Client.Photon.Hashtable();
PhotonNetwork.room.SetCustomProperties(properties, expectedProperties, true);
LogMessage("New Room Properties Set");
}

Run the hub scene and wait for PlayFab authentication to complete (1) .
Then load the Boxes Demo scene (2) .
Once the scene loads, wait for the peer to connect newly created room (1) .
Then select Execute Example in the top left corner (2) .
Observe the console output (3) .
Make sure no errors have occurred.
Don't forget to stop Unity from playing. This is done to ensure that we also receive RoomLeft and
RoomClosed events.
Navigate to the title Game Manager page, and observe the PlayStream panel. You should be able to see events
generated as a result of our CloudScript code handling Photon events.
1. Initially, our Photon instance had no opened room. When we launched the example, Photon has created the
room for the Boxes Demo.
2. The first player to join is the player who requested the room. So no RoomJoined Event was recorded. We
then executed our example code:
First, we raised a custom Room Event .
Then, we set a custom Room Proper ty .
Then we stopped the Unity play mode. This resulted in our client leaving the room.
3. Since our disconnected client was the last one, there are no more clients and Photon closes the room.
All the events should be logged into the PlayStream event flow, as shown on the following picture.
At this point, you have fully integrated Photon event support into your PlayFab title.
Unity3D (C#)
5/24/2022 • 2 minutes to read • Edit Online

Our Unity3d PlayFab SDK provides everything you need to access the PlayFab API. This includes models,
methods, an HTTP wrapper for sending and receiving web requests, and JSON serialization.
This SDK is auto-generated using our open-sourced tool—SDKGenerator. We generally build SDKs every other
week to stay current with the latest API changes.
Check out our Editor Extensions, for the easiest and fastest way to get started using PlayFab in Unity. This tool
provides a UI for managing SDK settings, as well as an automatic SDK upgrade with the ability to stay current
with the latest APIs.
PlayFab Party seamlessly integrate multiplayer networking and voice/text chat into Unity games. To get started,
see Party Unity Plugin.

Download links
Unity PlayFab SDK GitHub repo
Quick download link: Unity Editor Extensions for PlayFab SDK
Quick download link: Unity PlayFab SDK

Licenses
Unity3D licenses
Quickstart: PlayFab Client library for C# in Unity
5/24/2022 • 4 minutes to read • Edit Online

Get started with the PlayFab Client library for C# in Unity. Follow steps to install the package and try out
example code for a basic task.
This quickstart helps you make your first PlayFab API call in the Unity3d engine. Before continuing, make sure
you have completed Getting started for developers, which ensures you have a PlayFab account and are familiar
with the PlayFab Game Manager.

Requirements
A PlayFab developer account.
An installed copy of the Unity Editor. To install Unity for personal use via Unity Hub, or Unity+ for
professional use, see Download Unity.

NOTE
The PlayFab Unity3D SDK supports Unity Editor version 5.3 (released December 2015) and higher.

A Unity Project - this can be any of the following:


A brand new project. For more information, see Starting Unity for the first time.
A guided tutorial project. For more information, see Getting Started with Unity.
An existing project.
The PlayFab Unity3D SDK.

Download and install PlayFab SDK


Use the PlayFab Editor Extensions package to install the SDK. The PlayFab Editor Extensions are a stand-alone
Unity plug-in that streamlines installing the SDK and configuring the PlayFab settings for your Title. For
information about installing the SDK without using the PlayFab Editor Extensions, see Installing the PlayFab SDK
for Unity.
1. Download the PlayFab Unity Editor Extensions Asset Package.
2. Open your Unity Project.
3. Navigate to where you downloaded the file and double-click on the
PlayFabEditorExtensions.UnityPackage file to open the Impor t Unity Package dialog in the Unity Editor.
4. To import the PlayFab Unity Editor Extensions into your project, select Impor t .
5. When the import has completed, the PlayFab Unity Editor Extensions panel should open automatically. If
you've already created a PlayFab developer account, select the Log In link to log in with your PlayFab
username and password.

NOTE
If the panel did not open, or if you close the panel and want to reopen it, you can do so by selecting Window >
PlayFab > Editor Extensions
6. After logging in, the extension displays the SDK installation dialog.

7. Select Install PlayFab SDK to automatically import the SDK into your project or upgrade the version
that is currently installed.

Set your title settings


Before you can make an API call, you must specify the Title to receive the call in the PlayFab Title Settings . To
set the Title:
1. Select SET MY TITLE in the Editor Extensions .

2. Select the Studio entry to open the studio drop-down menu. Select the studio that contains the Title to
which you would like to connect.
3. Select the Title ID entry to open a drop-down menu of Titles associated with the selected studio.
The Developer Secret Key is automatically set to the default secret key for the Title. For more information
about secret keys, see Secret key management.
Making your first API call
This part of the guide provides the minimum steps to make your first PlayFab API call. This example does not
provide any GUI or on-screen feedback. Confirmation is displayed in the Console log.
1. If your Unity Project doesn't already have a Scripts folder (HDRP and LWRP/URP templates have one by
default), right-click on the Assets folder in the Project panel and select Create > Folder .
2. In the Assets window, name the folder Scripts.
3. Right-click the Scripts folder and select Create > C# Script .
4. Name the script PlayFabLogin.
5. Double-click the file to open it in a code-editor. Depending on your settings/installed-programs, this is
likely Visual Studio or MonoDevelop.
6. In your code editor, replace the contents of PlayFabLogin.cs with the code shown below and save the file.
using PlayFab;
using PlayFab.ClientModels;
using UnityEngine;

public class PlayFabLogin : MonoBehaviour


{
public void Start()
{
if (string.IsNullOrEmpty(PlayFabSettings.staticSettings.TitleId)){
/*
Please change the titleId below to your own titleId from PlayFab Game Manager.
If you have already set the value in the Editor Extensions, this can be skipped.
*/
PlayFabSettings.staticSettings.TitleId = "42";
}
var request = new LoginWithCustomIDRequest { CustomId = "GettingStartedGuide", CreateAccount
= true};
PlayFabClientAPI.LoginWithCustomID(request, OnLoginSuccess, OnLoginFailure);
}

private void OnLoginSuccess(LoginResult result)


{
Debug.Log("Congratulations, you made your first successful API call!");
}

private void OnLoginFailure(PlayFabError error)


{
Debug.LogWarning("Something went wrong with your first API call. :(");
Debug.LogError("Here's some debug information:");
Debug.LogError(error.GenerateErrorReport());
}
}

IMPORTANT
The code shown above is not for use with mobile Titles. This is only an example, and shows how to log in with a
CustomID . To implement login for a mobile Title, use either LoginWithAndroidDeviceID, LoginWithIOSDeviceID,
or some form of social login such as LoginWithFacebook.

7. In the Hierarchy panel, right-click your scene, then select Create Empty (or Game Object > Create
Empty in older versions of Unity).
8. Select the new Game Object and in the Inspector panel, select Add Component .
9. From the component drop-down menu, select Scripts > PlayFabLogin .
For more information on creating and using scripts in the Unity Editor, see Creating and Using Scripts in the
Unity documentation.

Finish and execute


You are now ready to test out this sample.
Be sure to save all files and return to the Unity Editor
Press the Play button at the top of the editor
You should see the following in your Unity Console Panel.
TIP
Alternatively, you can log into PlayFab and navigate to the title in Game Manager, and select the PlayStream Monitor
tab. Each time you Alt+ TAB focus away from the actively running Unity Title, it passes an event which you can see and
confirm in the PlayStream Monitor.

For a list of all available client API calls, see PlayFab API References.

Next steps
This quickstart shows a simplified procedure for authenticating a user. For additional information on user
authentication, see Login basics and best practices.
Learn how to bind an account to multiple devices and login mechanisms: Account linking quickstart.
Installing the PlayFab SDK for Unity
5/24/2022 • 2 minutes to read • Edit Online

You have two options when installing the PlayFab Unity 3D SDK:
Install the PlayFab Unity Editor Extensions Asset Package. Then use Editor Extension to install the PlayFab
Unity 3D SDK and configure your Unity Project.
PlayFab Editor Extensions is a stand-alone Unity plug-in that streamlines getting started with PlayFab.
When a supported SDK is installed, additional service menus are available. These menus provide access
to SDK configurations. These configuration settings are saved in a combination of places to ensure that
the data persists throughout Unity compilations and deployments. For more information about the
PlayFab Editor Extensions, see the readme in the PlayFab/UnityEditorExtensions GitHub repo.
Install the PlayFab Unity 3D SDK directly without using PlayFab Unity Editor Extensions. When you use
this installation method, you configure your Unity Project directly by setting properties property values in
your code.
This content assumes you that you have a PlayFab developer account and an existing Unity Project.

Install the PlayFab Unity Editor Extensions and the PlayFab SDK
1. Download the PlayFab Unity Editor Extensions Asset Package.
2. Open your Unity Project.
3. Navigate to where you downloaded the file and double-click on the
PlayFabEditorExtensions.UnityPackage file to open the Impor t Unity Package dialog in the Unity Editor.
4. To import the PlayFab Unity Editor Extensions into your project, select Impor t .
5. When the import has completed, the PlayFab Unity Editor Extensions panel should open automatically. If
you've already created a PlayFab developer account, select the Log In link to log in with your PlayFab
username and password.

NOTE
If the panel did not open, or if you close the panel and want to reopen it, you can do so by selecting Window >
PlayFab > Editor Extensions
6. After logging in, the extension displays the SDK installation dialog.

7. Select Install PlayFab SDK to automatically import the SDK into your project or upgrade the version
that is currently installed.
Set your title settings
Before you can make an API call, you must specify the Title to receive the call in the PlayFab Title Settings . To
set the Title:
1. Select SET MY TITLE in the Editor Extensions .

2. Select the Studio entry to open the studio drop-down menu. Select the studio that contains the Title to
which you would like to connect.
3. Select the Title ID entry to open a drop-down menu of Titles associated with the selected studio.
Download and install the SDK only
To install the SDK without using the PlayFab Unity Editor Extensions:
1. Open your Unity project.
2. Download the PlayFab Unity3D SDK Asset Package from the PlayFab GitHub repo.
3. Navigate to where you downloaded the file, and double-click on the .UnityPackage file to open the Impor t
Unity Package dialog in the Unity Editor.
4. To import the PlayFab Unity3D SDK into your project, select Impor t .
Setting the Title ID without using the editor extensions
To set the title:
1. In the Unity Editor Project panel select the Assets folder.
2. Open the Assets > PlayFabSdk > Shared > Public > Resources folder.
3. Select the PlayFabSettings Asset.
4. In the Inspector window, set the Title ID and the Developer Secret Key .
NOTE
Refer to Secret key Management to find your secret key, also called a developer key to your PlayFab Title.
Unreal Engine (C++, Blueprints)
5/24/2022 • 2 minutes to read • Edit Online

Our Unreal Marketplace plugin provides everything you need to access the PlayFab API. This includes models,
methods, an HTTP wrapper for sending and receiving web requests, and JSON serialization. There is a C++
interface and a Blueprint interface, giving you the best of both worlds.
This SDK is auto-generated using our open-sourced tool—SDKGenerator. We generally build SDKs every other
week to stay current with the latest API changes.

Download links
Unreal Engine PlayFab SDK GitHub repo
Unreal Engine PlayFab SDK on Unreal Marketplace site (external link)
Quick download link for Unreal Engine PlayFab SDK
Quickstart: PlayFab client library for Unreal Engine
5/24/2022 • 7 minutes to read • Edit Online

Get started with the PlayFab plugin for the Unreal Engine. Follow this quickstart to install the PlayFab Unreal
Engine plugin and create example apps that use the C++ client library and the Blueprint interface.
You can use the PlayFab plugin for the Unreal Engine to manage LiveOps for your Title and perform admin,
client, and server operations such as:
Player authentication.
Managing virtual items and currency.
Creating social features such as friends lists.
API reference documentation | Library source code | Unreal Marketplace

Prerequisites
A PlayFab developer account.
An installation of Visual Studio that is configured for Unreal Engine. For information about configuring Visual
Studio, see Setting Up Visual Studio for Unreal Engine.
An installation of the Unreal Engine. For information about installing the Ureal Engine, see the Unreal Engine
installation guide.
An installation of the PlayFab Unreal plugin. You can install the Unreal plugin from the Unreal Engine
marketplace.

Create an Unreal project


In Unreal Engine, create a new Unreal Project. For detailed instructions, follow the Create a New Project guide.
1. For Project Categor y select Games .
2. In Select Template , select Blank .
3. In Project Settings , select either C++ or Blueprint .
4. Choose No Star ter Content .
5. Choose a name for your project such as MyProject .

Enable the PlayFab Plugin in your Unreal project


To enable the PlayFab Plugin:
1. From the Settings menu, under Game Specific Settings click Plugins .
2. Enable the PlayFab plugin and restart Unreal Engine as required.
Add PlayFab as a Module dependency in C++
In Visual Studio, add PlayFab as a module dependency in your C++ project:
1. From the View menu open Solution Explorer which displays your C++ project files.
2. In Solution Explorer, navigate to Solution\Games\YourProjectName\Source and open
YourProjectName.Build.cs .
3. Add the following line:
PrivateDependencyModuleNames.AddRange(new string[] { "PlayFab", "PlayFabCpp", "PlayFabCommon" });

4. Save your changes.

Generate the necessary Visual Studio project files


To update and generate the Visual Studio project files necessary to use the PlayFab plugin:
1. Open a file explorer window and navigate to folder where your project files are located.
2. In the root folder of the project, right-click the YouProjectName.uproject file.
3. From the context menu, select Generate Visual Studio project files .

Calling PlayFab with C++


The following steps walk you through creating a Tile that logs into PlayFab using a custom ID. For information
about logging in from a Blueprints project, see "Calling PlayFab from Unreal Blueprints" later in this article.
Create a new Actor
To create a new Actor:
1. From the File menu, click New C++ Class .
2. For Parent Class select Actor .
3. Name your actor LoginActor . After you create the Actor, Unreal Engine automatically opens your C++
development environment and loads LoginActor.cpp and LoginActor.h.

IMPORTANT
For the purposes of this quickstart, you must name the Actor LoginActor . If you give the Actor a different name,
you must update the sample code provided in this quickstart to match the new name.

4. Drag-and-drop your new Actor LoginActor from the Content Browser into the Viewport panel. It will
appear in the World Outliner pane. If you don't see your LoginActor , select the Show or hide the
source panel icon. Then select the name of your project under the C++ classes.
Add PlayFab API calls to your C++ LoginActor
In this quickstart you use LoginWithCustomID to perform the log in. Log in using LoginWithCustomID is easy to
implement but is of limited usefulness in the scenario of a published Title. Before you launch your Title, see the
Login basics and best practices for information about implementing robust log in functionality.
The LoginWithCustomID call is made in your LoginActor . To add the PlayFab specific code to your LoginActor :
1. Replace the contents of LoginActor.h with the code shown below.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "PlayFab.h"
#include "Core/PlayFabError.h"
#include "Core/PlayFabClientDataModels.h"
#include "LoginActor.generated.h"

UCLASS()
class ALoginActor : public AActor
{
GENERATED_BODY()
public:
ALoginActor();
virtual void BeginPlay() override;
void OnSuccess(const PlayFab::ClientModels::FLoginResult& Result) const;
void OnError(const PlayFab::FPlayFabCppError& ErrorResult) const;

virtual void Tick(float DeltaSeconds) override;


private:
PlayFabClientPtr clientAPI = nullptr;
};

2. Replace the contents of LoginActor.cpp with the following code.


#include "LoginActor.h"
#include "Core/PlayFabClientAPI.h"

ALoginActor::ALoginActor()
{
PrimaryActorTick.bCanEverTick = true;
}

void ALoginActor::BeginPlay()
{
Super::BeginPlay();

clientAPI = IPlayFabModuleInterface::Get().GetClientAPI();
clientAPI->SetTitleId(TEXT("144"));

PlayFab::ClientModels::FLoginWithCustomIDRequest request;
request.CustomId = TEXT("GettingStartedGuide");
request.CreateAccount = true;

clientAPI->LoginWithCustomID(request,
PlayFab::UPlayFabClientAPI::FLoginWithCustomIDDelegate::CreateUObject(this,
&ALoginActor::OnSuccess),
PlayFab::FPlayFabErrorDelegate::CreateUObject(this, &ALoginActor::OnError)
);
}

void ALoginActor::OnSuccess(const PlayFab::ClientModels::FLoginResult& Result) const


{
UE_LOG(LogTemp, Log, TEXT("Congratulations, you made your first successful API call!"));
}

void ALoginActor::OnError(const PlayFab::FPlayFabCppError& ErrorResult) const


{
UE_LOG(LogTemp, Error, TEXT("Something went wrong with your first API call.\nHere's some debug
information:\n%s"), *ErrorResult.GenerateErrorReport());
}

void ALoginActor::Tick(float DeltaTime)


{
Super::Tick(DeltaTime);
}

TIP
Intellisense in Visual Studio will indicate that it cannot locate the include files and the PlayFab namespace. You can safely
disregard these warnings. When you run your project it will build and execute correctly.

Finish and execute with C++


Now you're ready to test a call to PlayFab from Unreal Engine in C++. The results of your test call will be
displayed in the Output Log of Unreal Engine.
In Unreal Engine:
1. Display the Output Log from the Windows menu, select Developer Tools and enable Output Log .
2. In the toolbar, select Compile and wait for Unreal Engine to finish compiling. While your code is compiling,
Unreal displays a "Compiling C++ Code".
3. Select Play . When the code runs, Unreal displays the following in the Output Log window:
LogTemp: Congratulations, you made your first successful API call!
Calling PlayFab from Unreal Blueprints
This section guides you through creating a Blueprint structure, which uses the PlayFab API to call
LoginWithCustomID. Log in using LoginWithCustomID is easy to implement but is of limited usefulness in the
scenario of a published Title. Before you launch your Title, see the Login basics and best practices for
information about implementing robust log in functionality.

TIP
If you start from a Blueprint project, you must convert it to a C++ project for the PlayFab Blueprint Actions to function.

Create a Blueprint structure


In Unreal Engine, from the toolbar, select Open Level Blueprint .

The EventGraph opens and is prepopulated with two Actions. Event BeginPlay and Event Tick .
Actions used in this quickstart:
Set Play Fab Settings
Login with Custom ID
Make ClientLoginWithCustomIDRequest
AddCustomEvent x2
Break PlayFabError
Print String x2

Create your Blueprint as follows:


Select the output pin on Event BeginPlay and drag it to an open location in the Event Graph . In the
Executable Actions dialog, search for Set Play Fab Settings and select it to add it to your Blueprint. In
Set Play Fab Settings , if Game Title id is blank, set it to the Title ID of your game.

For information on retrieving your Title id, see "Retrieving your TitleId" in Getting started for
developers.
Select the output pin on Set Play Fab Settings and drag it to an open location. In the Executable
Actions dialog, search for Login with Custom ID and select it to add it to your Blueprint.
Select the Request pin on Login with Custom ID and drag it to an empty location. From the Actions
providing a(n) Client Login With Custom IDRequest Structure select
Make ClientLoginWithCustomIDRequest .

On Make ClientLoginWithCustomIDRequest :
Select Create Account .
Set the Custom Id to GettingStartedGuide.
On Login with Custom ID select the On Success pin and drag it to an empty location. in the Actions
providing a(n) Delegate search for Add Custom Event and select it to add it to your Blueprint.
Name it OnLogin .
Select the On Failure pin and drag it to an empty location. in the Actions providing a(n) Delegate
search for Add Custom Event and select it to add it to your Blueprint.
Name it OnFailure .
Select the output pin on OnLogin and drag it to an empty location. In the Executable Actions dialog
search for Print String and select it to add it to the Blueprint.
On Print String set the In String value to "Congratulations, you made your first successful PlayFab
API call using Blueprint!".
Select the output pin of OnFailure nd drag it to an empty location. In the Executable Actions dialog
search for Print String and select it to add it to the Blueprint.
Select the Error pin on OnFailure and drag it to an empty location. In the Actions providing a(n)
string dialog search for Break PlayFabError and select it to add it to the Blueprint. In the Actions
taking a(n) Play Fab error structure dialog search for Break PlayFabError and select it to add it to
the Blueprint.
Connect the Error Message pin of Break PlayFabError to the In String pin of on failure Print String
Action.
When you are finished your Blueprint will look similar to the following:
Save the Blueprint, and close the Blueprint Editor window.
Execute a PlayFab call with Blueprint
1. On the toolbar, select the Play button.
2. When the Blueprint runs, the following output is shown in the Viewport window.

Congratulations, you made your first successful PlayFab API call using Blueprint!

Additional Resources
Unreal Engine documentation for Blueprints Visual Scripting.
Unreal Engine Programming Guide.
ActionScript
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
The PlayFab ActionScript SDK has been deprecated. Information on this page is no longer maintained and updated.

Adobe ended support for Adobe Flash Player and has been completely removed from common browsers. For
more information, see Adobe Flash Player End of Life General Info (external site).
Our ActionScript SDK provides everything you need to access the PlayFab API. This includes models, methods,
and an HTTP wrapper for sending and receiving web requests and JSON serialization.

Download links
Final SDK release
ActionScript PlayFab SDK GitHub repo
Quick download link for ActionScript PlayFab SDK
ActionScript quickstart for Flash
5/24/2022 • 6 minutes to read • Edit Online

This quickstart helps you make your first PlayFab API call using ActionScript.
Before you can call any PlayFab API, you must have a PlayFab developer account.

ActionScript3 project setup


OS: This guide is for Windows 10. However, the steps for Mac should be similar, but probably not identical.

Installation
These steps describe building an AS3 project using entirely free tools. As such, this might be more complicated
than something like Adobe Flash Builder. The instructions are the result of lots of experimentation and testing,
rather than expert knowledge. If you're already aware of simpler installation steps, feel free to skip to the next
section.

Downloads
For environment variable instructions below, anything in {curly braces} should be replaced with the actual
installation path (don't put actual curly braces in your environment variables).
1. Install the Adobe Air SDK: https://www.adobe.com/devnet/air/air-sdk-download.html.
Remember your installation path {AirSdkLocation} since you will use it below.
2. Install the Adobe Flex SDK: https://www.adobe.com/devnet/flex/flex-sdk-download.html
Remember your installation path {FlexSdkLocation}, and modify your system environment variables:
Add {FlexSdkLocation}/bin to your PATH environment variable. For example, if you install to
C:/dev/flex_sdk_4.6, then set FLEX_HOME=C:/dev/flex_sdk_4.6
Add a FLEX_HOME system environment variable, and set it to {FlexSdkLocation} For example, if you
install to C:/dev/flex_sdk_4.6, then add C:/dev/flex_sdk_4.6/bin to your PATH
3. Open two Explorer windows: {AirSdkLocation} and {FlexSdkLocation}
4. Select All in the {AirSdkLocation} folder.
5. Copy and Paste the contents of {AirSdkLocation} over the top of {FlexSdkLocation}. This will replace some
existing files, and that's correct.
6. Download the PlayFab ActionScriptSD ActionScript SDK zip file, and extract it to a location of your choice
{PlayFabAs3Location}.

NOTE
Updates to environment variables sometimes require a computer restart.

7. Create a new empty folder for your GettingStartedAs3 Project, with the following three empty files:
A new text file called GettingStarted
A new text file called GettingStarted.xml
A new text file called buildAndRun.bat
8. Import the PlayFab ActionScriptSDK into this project:
In Windows-Explorer, navigate to {PlayFabAs3Location}/PfApiTest
Select the "com" folder, and copy it to your project folder. This contains a subfolder called "playfab"
which is the PlayFabSDK.
9. Create the flexcfg.xml file.
Open a command window in your project folder. Hold shift and right-click in the empty-white-
space of the Explorer window.

In the new console window enter this command:


mxmlc -dump-config flexcfg.xml
This should create a new text file called flexcfg.xml
We will modify all these project files in the next section.
Installation complete!

Set up your first API call


This quickstart provides the minimum steps for making your first PlayFab API call. Confirmation is visible in the
app.
In your favorite text editor, update the contents of buildAndRun.bat as follows:

call mxmlc GettingStarted.as -load-config flexcfg.xml


echo Build Code is %errorlevel%
if %errorlevel% EQU 0 (
call adl GettingStarted.xml
)
pause

In your favorite text-editor, update the contents of GettingStarted , as shown below.


package
{
import flash.display.Sprite;
import flash.text.*;
import com.playfab.PlayFabSettings;
import com.playfab.ClientModels.*;
import com.playfab.PlayFabClientAPI;

public class GettingStarted extends Sprite


{
public var textField:TextField;

public function GettingStarted()


{
textField = new TextField();
textField.x=0; textField.y=0; textField.width=2000; textField.height=2000;
textField.text = "Login pending...";
stage.addChild(textField);

PlayFabSettings.TitleId = "144"; // Please change this value to your own titleId from PlayFab
Game Manager

var loginRequest:com.playfab.ClientModels.LoginWithCustomIDRequest = new


com.playfab.ClientModels.LoginWithCustomIDRequest();
loginRequest.TitleId = PlayFabSettings.TitleId;
loginRequest.CustomId = "GettingStartedGuide";
loginRequest.CreateAccount = true;
PlayFabClientAPI.LoginWithCustomID(loginRequest, OnLoginSuccess, OnLoginFail);
}

private function OnLoginSuccess(result:com.playfab.ClientModels.LoginResult) : void


{
textField.text = "Congratulations, you made your first successful API call!";
}

private function OnLoginFail(error:com.playfab.PlayFabError) : void


{
var fullMessage:String = error.errorMessage;
for (var key:String in error.errorDetails) {
fullMessage += "\n";
fullMessage += key + ": " + error.errorDetails[key];
}
textField.text = "Something went wrong with your first API call.\n" +
"Here's some debug information:\n" +
fullMessage;
}
}
}

In your favorite text-editor, update the contents of GettingStarted.xml as follows:

<?xml version="1.0" encoding="UTF-8"?>


<application xmlns="http://ns.adobe.com/air/application/22.0">
<id>samples.android.GettingStarted</id>
<versionNumber>0.0.1</versionNumber>
<filename>GettingStarted</filename>
<initialWindow>
<content>GettingStarted.swf</content>
</initialWindow>
<supportedProfiles>mobileDevice</supportedProfiles>
</application>

In your favorite text-editor, open flexcfg.xml and make the following changes:
flexcfg.xml is a large file, but we will only be making small changes.
The <external-library-path> and <library-path> sections need to be converted to absolute paths.
Replace these two sections, as shown below.

<external-library-path>
<path-element>libs/player/{targetPlayerMajorVersion}.{targetPlayerMinorVersion}/playerglobal.swc</path-
element>
</external-library-path>
...
<library-path>
<path-element>libs</path-element>
<path-element>locale/{locale}</path-element>
</library-path>

With absolute paths based on your FlexSdk installation:


In this case, we installed Flex to C:/dev/flex_sdk_4.6/ , so the replacements look similar to the example that
appears below.

<external-library-path>
<path-element>C:/dev/flex_sdk_4.6/frameworks/libs/player/{targetPlayerMajorVersion}.
{targetPlayerMinorVersion}/playerglobal.swc</path-element>
</external-library-path>
...
<library-path>
<path-element>C:/dev/flex_sdk_4.6/frameworks/libs</path-element>
<path-element>C:/dev/flex_sdk_4.6/frameworks/locale/{locale}</path-element>
</library-path>

Finish and execute


1. In Windows explorer, double-click buildAndRun.bat .
After running, note the new file GettingStar ted.swf - This is our compiled project, and it will open
two new windows, which collectively should look like the example shown below.

At this point, you can start making other api calls, and building your game.
For a list of all available client API calls, see our PlayFab API References documentation.
Happy coding!

Deconstruct the code


This optional last section describes every file in the ActionScript3 Project in detail.
buildAndRun.bat
This file is a simple Windows batch file which compiles and executes this project.
call mxmlc GettingStarted.as -load-config flexcfg.xml .
mxmlc is the Flex compiler for ActionScript3.
The rest is just telling the compiler what to do, specifically, build our GettingStarted.as
project, and use the flexcfg.xml file as configuration settings.
errorlevel is an automatic Windows variable you can use to check whether the previous
command succeeded.
call adl GettingStarted.xml

adl is Air Debug Launcher, which launches a compiled swf file as a Windows app.
GettingStar ted.xml
This is a bare bones ActionScript project definition file. The first section of this Adobe guide
describes everything in detail.
flexcfg.xml
This file tells the mxmlc compiler all of the variables and settings it should use.
We only made trivial changes from the default setting.
GettingStarted.as
This file contains the only code relevant to the PlayFab SDK.
textField:
These lines are just controlling the GUI output, displaying the results of the API call.
PlayFabSettings.TitleId = "144";

Every PlayFab developer creates a title in Game Manager. When you publish your game,
you must code that titleId into your game. This lets the client know how to access the
correct data within PlayFab. For most users, just consider it a mandatory step that makes
PlayFab work.
var loginRequest:com.playfab.ClientModels.LoginWithCustomIDRequest = new
com.playfab.ClientModels.LoginWithCustomIDRequest();

Most PlayFab API methods require input parameters, and those input parameters are
packed into a request object.
Every API method requires a unique request object, with a mix of optional and
mandatory parameters.
For LoginWithCustomIDRequest , there is a mandatory parameter of CustomId ,
which uniquely identifies a player and CreateAccount , which allows the creation
of a new account with this call.
For login, most developers will want to use a more appropriate login method.
See the PlayFab Login documentation for a list of all login methods, and input
parameters. Common choices are:
LoginWithAndroidDeviceID
LoginWithIOSDeviceID
LoginWithEmailAddress
PlayFabClientAPI.LoginWithCustomID(loginRequest, OnLoginSuccess, OnLoginFail);

This begins the async request to LoginWithCustomID . When complete, it will call
OnLoginSuccess or OnLoginFail for success or failure respectively.

Inside of OnLoginSuccess :
The result object of many API success callbacks will contain the requested information.
LoginResult contains some basic information about the player, but for most users, login
is simply a mandatory step before calling other APIs.
Inside of OnLoginFailure :
API calls can fail for many reasons, and you should always attempt to handle failure.
Why API calls fail (In order of likelihood)
PlayFabSettings.TitleId is not set. If you forget to set titleId to your title, then
nothing will work.
Request parameters. If you have not provided the correct or required information
for a particular API method, then it will fail. See error.errorMessage,
error.errorDetails for more info.
Device connectivity issue. Cell-phones lose/regain connectivity constantly, and so
any API call at any time can fail randomly, and then work immediately after. Going
into a tunnel can disconnect you completely.
PlayFab server issue. As with all software, there can be issues. See our release
notes for updates.
The internet is not 100% reliable. Sometimes the message is corrupted or fails to
reach the PlayFab server.
If you are having difficulty debugging an issue, and the information within the error
callback is not sufficient, please visit us on our forums.
JavaScript
5/24/2022 • 2 minutes to read • Edit Online

Our JavaScript SDK provides everything you need to access the PlayFab API. This includes models, methods, an
HTTP wrapper for sending and receiving web requests, and JSON serialization.
This SDK is auto-generated using our open-sourced tool—SDKGenerator. We generally build SDKs every other
week to stay current with the latest API changes.
There are several methods to get this SDK. One method is to use our Content Delivery Network (CDN). For more
details, see our blogpost about JavaScript SDK via CDN.
Alternatively, you can also obtain this SDK via NPM using the command npm install playfab-web-sdk .

Download links
JavaScript PlayFab SDK GitHub repo
Quick download link for JavaScript PlayFab SDK
Install SDK via NPM: npm install playfab-web-sdk

Licenses
Javascript licenses
QuickStart: PlayFab client library for JavaScript
5/24/2022 • 5 minutes to read • Edit Online

Get started with the PlayFab client library for JavaScript to authenticate a player. Follow steps to install the
package and try out example code for basic tasks.

Prerequisites
A PlayFab developer account. For information about creating a Title and finding TitleId, see Game Manager
QuickStart.
The QuickStart guide works in any operating system capable of running a web browser.

JavaScript project setup


Before you can call any PlayFab API, you must have a PlayFab developer account. For information about creating
a Title and finding TitleId, see Game Manager QuickStart.
OS: This guide works in any OS capable of running a web browser.
To set up a new project, create a new folder with two empty text files:
PlayFabGettingStarted.html
PlayFabGettingStarted.js

That's it - PlayFab installation complete!

Code examples
This guide provides the minimum steps to make your first PlayFab API call. Confirmation is visible on the
webpage. For more information about parameters and return values, we recommend using Postman template
first.
Authenticate the client
In your favorite text-editor, update the contents of PlayFabGettingStarted.html as follows:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>PlayFab JavaScript Unit Tests</title>
<script type="text/javascript" src="https://download.playfab.com/PlayFabClientApi.js"></script>
<script type="text/javascript" src="PlayFabGettingStarted.js"></script>
</head>
<body>
PlayFab Getting Started Guide<br />
TitleID: <input type="text" id="titleId" value="144"><br />
CustomID: <input type="text" id="customId" value="GettingStartedGuide"><br />
<input type="button" value="Call LoginWithCustomID" onclick="DoExampleLoginWithCustomID()"><br />
Result:<br />
<textarea id="resultOutput" cols="60" rows="5"></textarea><br />
</body>
</html>
In your favorite text-editor, update the contents of PlayFabGettingStarted.js as follows:

function DoExampleLoginWithCustomID(){
PlayFab.settings.titleId = document.getElementById("titleId").value;
var loginRequest = {
// Currently, you need to look up the required and optional keys for this object in the API
reference for LoginWithCustomID. See the Request Headers and Request Body.
TitleId: PlayFab.settings.titleId,
CustomId: document.getElementById("customId").value,
CreateAccount: true
};

PlayFabClientSDK.LoginWithCustomID(loginRequest, LoginCallback);
}

// callback functions take two parameters: result and error


// see callback functions in JavaScript if unclear
var LoginCallback = function (result, error) {
if (result !== null) {
document.getElementById("resultOutput").innerHTML = "Congratulations, you made your first successful
API call!";
} else if (error !== null) {
document.getElementById("resultOutput").innerHTML =
"Something went wrong with your first API call.\n" +
"Here's some debug information:\n" +
PlayFab.GenerateErrorReport(error);
}
}

To look up the correct format for the loginRequest object in this example, see the API reference for
LoginWithCustomID.

Run the code


1. Open PlayFabGettingStarted.html in your favorite browser.
2. Click the Call LoginWithCustomID button.
3. You should see the following text in the Result section: "Congratulations, you made your first successful API
call!"
At this point, you can start making other api calls, and building your game.
For a list of all available client API calls, see PlayFab API References documentation.

Deconstruct the code


This section describes each part of the code in detail.
The HTML file has a few important lines:

<script type="text/javascript" src="https://download.playfab.com/PlayFabClientApi.js"></script>

This line loads the Client-SDK directly from the PlayFab CDN. Our CDN always hosts the latest version of
PlayFabSDK. It may be safer for you to download the files, and use a fixed version: PlayFab JavaScript SDK

<script type="text/javascript" src="PlayFabGettingStarted.js"></script>


...
<input type="button" value="Call LoginWithCustomID" onclick="DoExampleLoginWithCustomID()"><br />
As you can see above, PlayFabGettingStarted.js contains the DoExampleLoginWithCustomID function. These lines
bind our js file to our webpage, and invoke the DoExampleLoginWithCustomID function in that script. Everything
else is just GUI.
The functions in PlayFabClientSDK are named after the corresponding HTTP requests. For example, the
corresponding HTTP request for the LoginWithCustomID function is also named"LoginWithCustomID." The
Request Body is packed into the JavaScript request object as keys and values. The Session Ticket will be saved
from login, so client calls need not incorporate the Session Ticket from the Request Header.
Line by line breakdown for PlayFabGettingStarted.js
PlayFab.settings.titleId = "xxxx";

Every PlayFab developer creates a title in Game Manager. When you publish your game, you
must code that titleId into your game. This lets the client know how to access the correct data
within PlayFab. For most users, just consider it a mandatory step that makes PlayFab work.
var loginRequest = { TitleId: PlayFab.settings.titleId, CustomId: "GettingStartedGuide",
CreateAccount: true };

Most PlayFab API methods require input parameters, and those input parameters are packed
into a request object
Every API method requires a unique request object, with a mix of optional and mandatory
parameters
For LoginWithCustomID , there is a mandatory parameter of CustomId , which uniquely
identifies a player and CreateAccount , which allows the creation of a new account with
this call. TitleId is another mandatory parameter in JavaScript, and it must match
PlayFab.settings.titleId .
For information about where to find TitleId , see Game Manager QuickStart.
In this case, TitleId , customId , and CreateAccount are from the Request Body of
LoginWithCustomID . The Request Body fields are included as keys and values in the request object.
The Session Ticket in the Request Header will be saved from login, so the SessionTicket is not
included in the request object.
PlayFabClientSDK.LoginWithCustomID(loginRequest, LoginCallback);

This begins the async request to LoginWithCustomID , which will call LoginCallback when the
API call is complete.
For login, most developers will want to use a more appropriate login method.
See PlayFab Login Documentation for a list of all login methods, and input parameters.
Common choices are:
LoginWithAndroidDeviceID
LoginWithIOSDeviceID
LoginWithEmailAddress
If new to JavaScript, we recommend that developers read about callback functions.
LoginCallback contains two parameters: result, error
When successful, error will be null, and the result object will contain the requested information,
according to the API called.
This result contains some basic information about the player, but for most users, login is simply
a mandatory step before calling other APIs.
If error is not null , your API call has failed.

Troubleshooting
API calls can fail for many reasons, and you should always attempt to handle failure.
The error object includes the error name, error code, and error message. Together, this information should be
sufficient to diagnose your error.
Global API Method Error Codes can be found in PlayFab's Global API Method Error Codes.
Why API calls fail (In order of likelihood)
PlayFabSettings.TitleId is not set. If TitleId is not set, then nothing will work.
Request parameters. If you have not provided the correct or required information for a particular API
call, then it will fail. See error.errorMessage, error.errorDetails , or error.GenerateErrorReport() for
more info.
Device connectivity issue. Cell-phones lose/regain connectivity constantly, and so any API call at any
time can fail randomly, and then work immediately after. Going into a tunnel can disconnect you
completely.
PlayFab server issue. As with all software, there can be issues. See our release notes for updates.
The internet is not 100% reliable. Sometimes the message is corrupted or fails to reach the PlayFab
server.
If you are having difficulty debugging an issue, and the information within the error information is not
sufficient, please visit us on our forums.

Next Steps
This quickstart shows a simplified procedure for authenticating a user. For additional information about user
authentication, see Login basics and best practices.
Happy coding!
Lua
5/24/2022 • 2 minutes to read • Edit Online

Our SDK provides everything you need to access the PlayFab API. This includes models, methods, an HTTP
wrapper for sending and receiving web requests, and JSON serialization. With the Lua SDK, you gain support for
Defold and Corona game engines.
This SDK is auto-generated using our open-sourced tool—SDKGenerator. We generally build SDKs every other
week to stay current with the latest API changes.

Download links
Lua PlayFab SDK GitHub repo
Quick download link for Lua PlayFab SDK

Licenses
Lua licenses
Lua quickstart for Corona
5/24/2022 • 4 minutes to read • Edit Online

This quickstart assists you in making your first PlayFab API call in the Corona engine.
Before you can call any PlayFab API, you must have a PlayFab developer account.

Corona Project Setup


OS: This quickstart is written for Windows 10. However, it should also work well with a Mac.
1. Download and install Corona: https://coronalabs.com/.
2. Run Corona, and create a new project. The following link has information that can assist you with your
first-time steps if you haven't done them: https://docs.coronalabs.com/guide/start/installWin/index.html
3. Once you have installed, logged in, and created a new project, you should see several windows that look
something like the example shown below.

4. Activate the PlayFab Client plugin on the Corona Marketplace:


https://marketplace.coronalabs.com/plugin/playfab-client
5. The PlayFab installation is complete!

Setting up your first API call


This guide provides the minimum steps required to make your first PlayFab API call. Confirmation is visible in
the Corona Engine output log.
In your favorite text-editor, add the following lines to build.settings .
settings =
{
-- ADD THESE THREE LINES at the top, leave everything else as-is
plugins = {
["plugin.playfab.client"] = { publisherId = "com.playfab" }
},

-- Other existing lines...


}

NOTE
To look up the correct format for the loginRequest object in this example, see the API reference for LoginWithCustomID.

In your favorite text-editor, replace the contents of the main.lua file with the contents shown below.

local pfClient = require("plugin.playfab.client")


local PlayFabClientApi = pfClient.PlayFabClientApi
PlayFabClientApi.settings.titleId = "144"

local loginRequest = {
-- See the API reference for LoginWithCustomID.
CustomId = "GettingStartedGuide",
CreateAccount = true
}
PlayFabClientApi.LoginWithCustomID(loginRequest,
function(result) print("Congratulations, you made your first successful API call!") end,
function(error) print("Something went wrong with your first API call.\nHere's some debug information:\n"
.. error.errorMessage) end
)

Finish and execute


Corona automatically executes the project source immediately when you save. So as soon as you update and
save these two files, you should see this:
At this point, you can start making other API calls, and building your game. For a list of all available client API
calls, see our PlayFab API References documentation.
Happy coding!

Deconstruct the code


This optional last section describes each part of our example above, line-by-line.
build.settings
plugins = {
This invokes the Corona plugin system, and tells it to download and install Corona Marketplace
plugins in your project
["plugin.playfab.client"] = { publisherId = "com.playfab" }
This tells it to download the PlayFab Client plugin specifically.
main.lua
require() lines:
This is the minimal imports you need to make PlayFab API calls.
PlayFabClientApi.settings.titleId = "xxxx"
Every PlayFab developer creates a title in Game Manager. When you publish your game, you
must code that titleId into your game. This lets the client know how to access the correct data
within PlayFab. For most users, just consider it a mandatory step that makes PlayFab work.
local loginRequest = { CustomId = "GettingStartedGuide", CreateAccount = true }
Most PlayFab API methods require input parameters, and those input parameters are packed
into a request object
Every API method requires a unique request object, with a mix of optional and mandatory
parameters
For LoginWithCustomIDRequest , there is a mandatory parameter of CustomId , which
uniquely identifies a player and CreateAccount , which allows the creation of a new
account with this call.
PlayFabClientApi.LoginWithCustomID(loginRequest, {OnLoginSuccess-function}, {OnLoginError-
function})
This begins the async request to LoginWithCustomID , which will call the first ( OnLoginSuccess )
callback if successful, or the second ( OnLoginError ) function for failures.
For login, most developers will want to use a more appropriate login method.
See the PlayFab Login documentation for a list of all login methods, and input parameters.
Common choices are:
LoginWithAndroidDeviceID
LoginWithIOSDeviceID
LoginWithEmailAddress
OnLoginSuccess is any function which accepts a single parameter (result).
The result object will contain the requested information, according to the API called.
LoginResult contains some basic information about the player, but for most users, login
is simply a mandatory step before calling other APIs.
OnLoginError is any function which accepts a single parameter (error).
API calls can fail for many reasons, and you should always attempt to handle failure.
Why API calls fail (In order of likelihood):
PlayFabSettings.TitleId is not set. If you forget to set titleId to your title, then
nothing will work.
Request parameters. If you have not provided the correct or required information
for a particular API call, then it will fail. See error.errorMessage ,
error.errorDetails , or error.GenerateErrorReport() for more info.
Device connectivity issue. Cell-phones lose/regain connectivity constantly, and so
any API call at any time can fail randomly, and then work immediately after. Going
into a tunnel can disconnect you completely.
PlayFab server issue. As with all software, there can be issues. See our release
notes for updates.
The internet is not 100% reliable. Sometimes the message is corrupted or fails to
reach the PlayFab server.
If you are having difficulty debugging an issue, and the information within the error
information is not sufficient, please visit us on our forums.
Lua quickstart for Defold
5/24/2022 • 6 minutes to read • Edit Online

This quickstart assists you in making your first PlayFab API call using Defold.
Before you can call any PlayFab API, you must have a PlayFab developer account.

Defold project setup


OS: This guide is written for Windows 10. It should also work well with a Mac.
1. Create an account and download defold, or log in at https://www.defold.com/ (Uses Google O-Auth):
https://d.defold.com/stable/.
2. If you have not completed the Defold "Getting Started Tutorial", you should do that now.
3. Create a new project on the Defold Dashboard, as shown below.

4. Run Defold , and load your new project. You should see several windows that look something like the
example shown below.
5. Update the Project Settings, and include PlayFab in the dependencies:
https://github.com/PlayFab/LuaSdk/raw/master/Defold/PlayFabClientSdk.zip

6. Select: Project -> Fetch Libraries , and you should see a new built-in PlayFab folder, as shown below.
7. Create a few files:
main/PfGettingStar ted.gui
Right-click the "main" folder -> new -> Gui File -> PfGettingStar ted.gui .
main/PfGettingStar ted.gui_script
Right-click "main" folder -> new -> Gui Script File -> PfGettingStar ted.gui_script .
8. Hook up our new GUI in the main.collection.
Double-click main.collection to open it.
In the Outline panel:
Right-click Add Game Object (Optionally rename to PfGui ).
Right-Click the new object, Add Component From File...
PfGettingStarted.gui (Created above).
The Outline panel viewing main.collection should look like the example shown below.

The PlayFab installation is complete. This project isn't ready to build yet, but we'll fix that in the next step.

Set up your first API call


This guide will provide the minimum steps make your first PlayFab API call. Confirmation will be visible in the
game window.
1. In the Defold editor, double-click PfGettingStar ted.gui_script .
2. This should open the file for text editing.
3. Update the contents of PfGettingStarted.gui_script as shown below.

NOTE
To look up the correct format for the loginRequest object in this example, see the API reference for LoginWithCustomID.
local PlayFabClientApi = require("PlayFab.PlayFabClientApi")
local IPlayFabHttps = require("PlayFab.IPlayFabHttps")
local PlayFabHttps_Defold = require("PlayFab.PlayFabHttps_Defold")
IPlayFabHttps.SetHttp(PlayFabHttps_Defold) -- Assign the Defold-specific IHttps wrapper

PlayFabClientApi.settings.titleId = "144" -- Please change this value to your own titleId from PlayFab Game
Manager

function init(self)
local loginRequest = {
-- See the API reference for LoginWithCustomID
TitleId = PlayFabClientApi.settings.titleId,
CustomId = "GettingStartedGuide",
CreateAccount = true
}
PlayFabClientApi.LoginWithCustomID(loginRequest, OnLoginSuccess, OnLoginFailed)
end

function OnLoginSuccess(result)
local pfTestOutput = gui.get_node("pfOutput")
gui.set_text(pfTestOutput, "Congratulations, you made your first successful API call!")
end

function OnLoginFailed(error)
local pfTestOutput = gui.get_node("pfOutput")
local message = "Something went wrong with your first API call.\n"
local message = message .. "Here's some debug information:\n"
local message = message .. error.GenerateErrorReport()
gui.set_text(pfTestOutput, message)
end

4. In the Defold editor, right-click PfGettingStar ted.gui -> Open With -> Text Editor . Unfortunately, this
changes an internal setting in Defold, so:
Open it again: right-click PfGettingStar ted.gui -> Open With -> GUI Editor . This resets the
default back to normal.
Select the text-edit tab for PfGettingStar ted.gui .
Update the text contents of PfGettingStarted.gui as shown below.

script: "/main/PfGettingStarted.gui_script"
fonts {
name: "system_font"
font: "/builtins/fonts/system_font.font"
}
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
nodes {
position {
x: 100.0
y: 620.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 1080.0
y: 520.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ADD
text: "Logging in..."
font: "system_font"
id: "pfOutput"
xanchor: XANCHOR_LEFT
yanchor: YANCHOR_TOP
pivot: PIVOT_NW
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
layer: ""
inherit_alpha: true
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
outline_alpha: 1.0
shadow_alpha: 1.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
size_mode: SIZE_MODE_AUTO
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

Finish and execute


First, make sure everything is saved and select another tab. Then look for " * " markers - sometimes Defold
doesn't refresh.
Then, build your game (Ctrl+b or dropdowns: Project -> Build and Launch ). You should see the following text
on your screen:
"Congratulations, you made your first successful API call!"
For a list of all available client API calls, see our PlayFab API References documentation.
Happy coding!

Deconstruct the code


PfGettingStarted.gui

Our instructions for PfGettingStarted.gui are for expediency, not instruction. This file is a GUI
definition, which adds a text box to the screen, binds it to our other script:
PfGettingStarted.gui_script . You would NOT typically edit these files in text-form.
For proper instructions on how to build Defold GUI widgets, please read this guide:
GUI scenes in Defold
PfGettingStarted.gui_script

Require statements and setup.


PlayFabClientApi allows you to make Client API calls - This is why you're here.
IPlayFabHttps and PlayFabHttps_Defold:
The PlayFab Defold plugins are built on the PlayFab LuaSdk. The Lua language does not
have a proper HTTPS module. Each game-engine that uses Lua implements their own.
These two variables tell PlayFabSdk how to access HTTPS. You only need to do this once
in your project, in the first scene. Otherwise it's just required boilerplate
PlayFabClientApi.settings.titleId = "144"

Every project using PlayFab should create a unique title in the PlayFab website, which we call
Game Manager. Find your titleId in Game Manager, and replace 144 with your titleId .
function init(self)

Defold function - This is called when the gui is initialized.


local loginRequest = { TitleId = PlayFabClientApi.settings.titleId, CustomId =
"GettingStartedGuide", CreateAccount = true }

Most PlayFab API methods require input parameters, and those input parameters are packed
into a request object
Every API method requires a unique request object, with a mix of optional and mandatory
parameters
For LoginWithCustomIDRequest , there is a mandatory parameter of CustomId , which
uniquely identifies a player and CreateAccount , which allows the creation of a new
account with this call.
For login, most developers will want to use a more appropriate login method
See the PlayFab Login documentation for a list of all login methods, and input
parameters. Common choices are:
LoginWithAndroidDeviceID
LoginWithIOSDeviceID
LoginWithEmailAddress
PlayFabClientApi.LoginWithCustomID(loginRequest, OnLoginSuccess, OnLoginFailed)

This performs the API call using the request, and provides callback functions for success and fail
conditions.
function OnLoginSuccess(result)

The result object of many API success callbacks will contain the requested information.
LoginResult contains some basic information about the player, but for most users, login is
simply a mandatory step before calling other APIs.
function OnLoginFailed(error)

API calls can fail for many reasons, and you should always attempt to handle failure.
Why API calls fail (In order of likelihood)
PlayFabSettings.TitleId is not set. If you forget to set titleId to your title, then nothing
will work.
Request parameters. If you have not provided the correct or required information for
a particular API call, then it will fail. See error.errorMessage , error.errorDetails , or
error.GenerateErrorReport() for more info.

Device connectivity issue. Cell-phones lose/regain connectivity constantly, and so any


API call at any time can fail randomly, and then work immediately after. Going into a
tunnel can disconnect you completely.
PlayFab server issue. As with all software, there can be issues. See our release notes
for updates.
The internet is not 100% reliable. Sometimes the message is corrupted or fails to
reach the PlayFab server.
If you are having difficulty debugging an issue, and the information within the error
information is not sufficient, please visit us on our forums
local pfTestOutput = gui.get_node("pfOutput")

This is another Defold GUI function. It fetches the pfOutput GUI object defined in our
PfGettingStarted.gui file, and assigns it text to display to the user.
NodeJS
5/24/2022 • 2 minutes to read • Edit Online

Our Node.js SDK provides everything you need to access the PlayFab API. This includes models, methods, an
HTTP wrapper for sending and receiving web requests, and JSON serialization.
This SDK is auto-generated using our open-sourced tool—SDKGenerator. We generally build SDKs every other
week to stay current with the latest API changes.
This SDK can also be obtained via the npm install playfab-sdk command.

Download links
NodeJS PlayFab SDK GitHub repo
Quick download link for NodeJS PlayFab SDK
Install via NPM: npm install playfab-sdk

Licenses
Node Unit license
Quickstart: PlayFab client library for NodeJS
5/24/2022 • 5 minutes to read • Edit Online

Get started with the PlayFab client library for NodeJS to make your first PlayFab API call and authenticate a
player. Follow steps to install the package and try out example code for basic tasks.

Prerequisites
A PlayFab developer account. For information about creating a Title and finding TitleId, see Game Manager
QuickStart.
Node.js
Node must be in your PATH environment variable. If you used the installer, it's probably set for you to the
default location: C:/Program Files (x86)/nodejs/

Setting up
The following commands work on Windows, MacOS, and Linux.
1. Create a new folder for your project {NodeProjLocation}:
GettingStarted.js

2. Open a command window in your project folder.


3. Run this command:
npm install playfab-sdk --save

(Keep this window open (we'll use it again later.)


PlayFab installation complete!

Code examples
Authenticate the client
This guide provides the minimum steps for you to make your first PlayFab API call, without any GUI or on-
screen feedback. Confirmation is done with the Console log. For more information about parameters and return
values, we recommend using Postman template first.
In your favorite text editor, update the contents of GettingStarted.js as follows:

NOTE
To look up the correct format for the loginRequest object in this example, see the API reference for
LoginWithCustomID.
var PlayFab = require("./node_modules/playfab-sdk/Scripts/PlayFab/PlayFab");
var PlayFabClient = require("./node_modules/playfab-sdk/Scripts/PlayFab/PlayFabClient");

function DoExampleLoginWithCustomID() {
PlayFab.settings.titleId = "144";
var loginRequest = {
// Currently, you need to look up the correct format for this object in the API reference for
LoginWithCustomID. The Request Headers and Request Body are included as keys and values in the request
object.
TitleId: PlayFab.settings.titleId,
CustomId: "GettingStartedGuide",
CreateAccount: true
};

// For functions in the Node SDK, the first parameter will be the request object and the second
parameter will be the callback function. The callback function executes after the request returns.
PlayFabClient.LoginWithCustomID(loginRequest, LoginCallback);
}

function LoginCallback(error, result) {


if (result !== null) {
console.log("Congratulations, you made your first successful API call!");
} else if (error !== null) {
console.log("Something went wrong with your first API call.");
console.log("Here's some debug information:");
console.log(CompileErrorReport(error));
}
}

// This is a utility function we haven't put into the core SDK yet. Feel free to use it.
function CompileErrorReport(error) {
if (error == null)
return "";
var fullErrors = error.errorMessage;
for (var paramName in error.errorDetails)
for (var msgIdx in error.errorDetails[paramName])
fullErrors += "\n" + paramName + ": " + error.errorDetails[paramName][msgIdx];
return fullErrors;
}

// Kick off the acutla login call


DoExampleLoginWithCustomID();

Run the code


1. In the console window we opened during installation, run the command:
node GettingStarted.js

You should see the following text as a result:


"Congratulations, you made your first successful API call!"
Now, you can start making other API calls and building your game.
For a list of all available client API calls, see our PlayFab API References documentation.

Deconstruct the code


This section explains each part of the Node quickstart code in detail.
For the Node SDK, the functions in PlayFabClientSDK are named after the HTTP request. For example, the
corresponding HTTP request for the LoginWithCustomID function is also called "LoginWithCustomID." The
Request Headers and Request Body are packed into the JavaScript request object as keys and values.
Line-by-line breakdown for GettingStarted.js
PlayFab.settings.titleId = "xxxx";

Every PlayFab developer creates a title in Game Manager. When you publish your game, you
must code that TitleId into your game. This lets the client know how to access the correct data
within PlayFab. For most users, just consider it a mandatory step that makes PlayFab work.
var loginRequest = { TitleId: PlayFab.settings.titleId, CustomId: "GettingStartedGuide",
CreateAccount: true };

Most PlayFab API methods require input parameters, and those input parameters are packed
into a request object.
Every API method requires a unique request object, with a mix of optional and mandatory
parameters.
For LoginWithCustomIDRequest , there is a mandatory parameter of CustomId , which
uniquely identifies a player and CreateAccount , which allows the creation of a new
account with this call. TitleId is another mandatory parameter in JavaScript, and it
must match PlayFab.settings.titleId .
For information about where to find TitleId , see Game Manager QuickStart.
In this case, TitleId , customId , and CreateAccount are from the Request Body of LoginWithCustomID .
PlayFabClientSDK.LoginWithCustomID(loginRequest, LoginCallback);

This begins the async request to LoginWithCustomID , which will call LoginCallback when the API
call is complete.
For login, most developers will want to use a more appropriate login method.
See PlayFab Login documentation for a list of all login methods, and input parameters.
Common choices are:
LoginWithAndroidDeviceID
LoginWithIOSDeviceID
LoginWithEmailAddress
LoginCallback contains two parameters: error and result .
When successful, error will be null , and the result object will contain the requested information,
according to the API called.
This result contains some basic information about the player, but for most users, login is
simply a mandatory step before calling other APIs.
If error is not null , your API has failed.

Troubleshooting
API calls can fail for many reasons, and you should always attempt to handle failure.
The error object includes the error name, error code, and error message. Together, this information should be
sufficient to diagnose your error.
Why API calls fail (In order of likelihood):
PlayFabSettings.TitleId is not set. If you forget to set TitleId to your title, then nothing will work.
Request parameters. If you have not provided the correct or required information for a particular API
call, then it will fail. See error.errorMessage , error.errorDetails , or error.GenerateErrorReport() for
more info.
Device connectivity issue. Cell-phones lose/regain connectivity constantly, and so any API call at any
time can fail randomly, and then work immediately after. Going into a tunnel can disconnect you
completely.
PlayFab server issue. As with all software, there can be issues. See our release notes for updates.
The internet is not 100% reliable. Sometimes the message is corrupted or fails to reach the PlayFab server.
Global API Method Error Codes can be found in Global API Method Error Codes.
If you are having difficulty debugging an issue, and the information within the error information is not
sufficient, please visit us on our forums.

Next Steps
This quickstart shows a simplified procedure for authenticating a user. For additional information about user
authentication, see Login basics and best practices.
Happy coding!
Python
5/24/2022 • 2 minutes to read • Edit Online

IMPORTANT
This is a community supported SDK. Information on this page is no longer maintained and updated.

To learn how you can contribute and provide support for this SDK, refer to the ReadMe at Python PlayFab SDK
repo.
The team at Microsoft would no longer be providing official support for those using this SDK. You can continue
to get community support and updates at PlayFab forums.

NOTE
This topic provides information about the original version of the SDK and does not apply to the newer community
versions.

Python is a general purpose scripting language that is great for automation and server-side coding. Our Python
SDK is compatible with Python 3, and provides everything you need to access the PlayFab API.
You will need Python 3 installed on your machine to use this SDK.

Download links
Python PlayFab SDK GitHub repo
Python PlayFab SDK on Package Index (PyPI) repo (external link)
Python quickstart
5/24/2022 • 3 minutes to read • Edit Online

This quickstart is designed to help you make your first API call in Python 3.
A native Python project can be used a few ways:
As a stand-alone console Admin tool for maintaining your game.
Integration into an existing Python-based game engine.
For a list of Python game engines, see PythonGameLibraries on the python.org website.

Prerequisites
A PlayFab developer account.
Python 3 installed on your system.
You must also have the requests module installed.

NOTE
This beta release of the Python SDK only supports synchronous API calls, and your game loop may become blocked
performing PlayFab API calls. You may need to create your own async/threading model to avoid this problem.

If you are having difficulty debugging an issue, and the information provided the error information is not
sufficient, please visit us on our PlayFab forums.

Python project setup


1. From a command prompt, install the PlayFab Package using following command.

pip install playfab

If pip is not in your path, use the following command instead.

python -m pip install playfab

2. In your project directory, create a python script called playfab_test.py.

Set up your first API call


This quickstart provides the minimum steps to make your first PlayFab API call, without any GUI or on-screen
feedback. Confirmation is accomplished with a console print statement.
Replace the contents of your playfab_test.py file with the contents shown below.
from playfab import PlayFabClientAPI, PlayFabSettings

PlayFabSettings.TitleId = "144"

request = {
"CustomId": "GettingStartedGuide",
"CreateAccount": True
}

def callback(success, failure):


if success:
print("Congratulations, you made your first successful API call!")
else:
print("Something went wrong with your first API call. :(")
if failure:
print("Here's some debug information:")
print(failure.GenerateErrorReport())
PlayFabClientAPI.LoginWithCustomID(request, callback)

Finish and execute


Run the Python script using the command shown below.

python playfab_test.py

When it finishes, you should see the following text: "Congratulations, you made your first successful API call!"
At this point, you can start making other API calls and building your game. For a list of all available client API
calls, see our PlayFab API References documentation.
Happy coding!

Deconstruct the code


This optional last section describes each part of playfab_test.py in detail.
Imports
The PlayFab imports get you access to the APIs.
PlayFabSettings.TitleId = "144"

Every PlayFab developer creates a title in Game Manager. When you publish your game, you must
code that titleId into your game. This lets the client know how to access the correct data within
PlayFab. For most users, just consider it a mandatory step that makes PlayFab work.
request
Most PlayFab API methods require input parameters, and those input parameters are packed into a
dictionary object.
LoginWithCustomIDRequest takes a mandatory parameter of CustomId , which uniquely identifies
a player and returns the associated entity token, and CreateAccount , which allows the creation
of a new account with this call.
For login, most developers will want to use a more appropriate login method.
See the PlayFab Login documentation for a list of all login methods, and input
parameters. Common choices are:
LoginWithAndroidDeviceID
LoginWithIOSDeviceID
LoginWithEmailAddress
Callback
Success
If the API call was successful, success will contain the requested information and failure will be
None .
For login requests, success will contain basic information about the player, but for most users,
login is simply a mandatory step before calling other APIs.
Failure
If the API call wasn't successful, failure will contain some error information and success will be
None .
API calls can fail for many reasons, and you should always attempt to handle the failure.
Why API calls fail (In order of likelihood)
PlayFabSettings.TitleId is not set. If you forget to set titleId to your title, then
nothing will work.
Request parameters. If you have not provided the correct or required information for a
particular API call, then it will fail.
Device connectivity issue. Cell-phones lose/regain connectivity constantly, and so any
API call at any time can fail randomly, and then work immediately after. Going into a
tunnel can disconnect you completely.
PlayFab server issue. As with all software, there can be issues. See our release notes for
updates.
The internet is not 100% reliable. Sometimes the message is corrupted or fails to reach
the PlayFab server.
PlayFabClientAPI.LoginWithCustomID

Triggers the API call synchronously. When complete, the callback will be invoked.
General PlayFab samples
5/24/2022 • 2 minutes to read • Edit Online

These samples demonstrate how to use various PlayFab features.

DEM O N ST RAT ED
SA M P L E N A M E P L AT F O RM S EN GIN E DESC RIP T IO N C A PA B IL IT IES

PlayFabEconomy Android Android Studio This sample uses Login


Android's in-app In app
billing API and purchases
PlayFab client API, to
demonstrate an in-
app store that
exchanges real
money for virtual
items in PlayFab
Economy.

PlayFabSignIn iOS, Android, PC Unity This sample Login


demonstrates a
simple PlayFab sign
in flow. You may log
in with an
email/password,
create an account, or
log in as a guest.
Sign in information
may be remembered
across executions of
the sample.

PlayFabEventsUnity Android, iOS, PC Unity This sample Events


demonstrates
sending events from
within a Unity title.
The sample covers
player events, title
events and character
events.

PlayFabLeaderboards Android, iOS, PC Unity This sample Leaderboards


Unity demonstrates
reading and writing
from/to leaderboards
from within a Unity
title. The sample
covers lowest
score/best time, high
score and cumulative
score leaderboards.
DEM O N ST RAT ED
SA M P L E N A M E P L AT F O RM S EN GIN E DESC RIP T IO N C A PA B IL IT IES

SpaceRumble Android, iOS, PC Unity This sample User accounts


demonstrates a User title data
simple single-player Title data
mobile game. Events that
trigger
CloudScript
Leaderboards

ThunderRumble PC, Xbox C++ DirectX Native This sample Login


demonstrates Matchmaking
scalable cloud Multiplayer
dedicated server Servers
functionality, using
the PlayFab
Multiplayer Servers
technology to build a
complete end-to-end
game experience.

Endless Runner iOS, Android, PC Unity Demonstrates - Log in


Integration of - Player Data
PlayFab into a game - Leaderboards
from the Unity Asset - Telemetry
Store

See also
Multiplayer Servers samples
Party samples
Multiplayer Servers samples and resources
5/24/2022 • 2 minutes to read • Edit Online

This topic lists samples and resources for PlayFab Multiplayer Game Servers.

Samples
Main repo for all the samples
Wrapper (Windows and Linux)—Using the sample
MpsAllocator—Learn to call frequently used APIs
Windows Runner C#—Using the sample
OpenArena (Linux)
Matchmaking with Server (Using a C# game title)
UnityMirror—Use Unity game engine with PlayFab Multiplayer Servers

Resources
PlayFabMultiplayerAPI module
PlayFab LocalMultiplayerAgent

See also
SDKs overview
Party samples
5/24/2022 • 2 minutes to read • Edit Online

This topic lists all the Azure PlayFab Party samples that are currently available.
If there's a specific sample that you'd like to have, let us know by writing a post on our forums.
Access to samples for Nintendo Switch, PlayStation®4, PlayStation®5, Google Stadia, PC (GDK), and Xbox
(GDK) requires special approval and adherence to platform policies. For more information, see Request access
for SDKs and samples.

List of samples
SA M P L E DESC RIP T IO N P L AT F O RM / O P ERAT IN G SY ST EM

Chat app Demonstrates Party chat usage with Windows 10, Windows 8.1, Windows
full speech-to-text and text-to-speech 7, Android, iOS, Stadia, Switch,
capabilities. PlayStation 4, PlayStation 5

Bumble Rumble Demonstrates usage of Party Windows 10, Windows 8.1, Xbox (XDK)
networking, matchmaking, and
accessible voice chat—full speech-to-
text and text-to-speech capabilities. It
doesn't include Xbox Live requirements
and game invites.

NetRumble Demonstrates how to use Party, Party PC and Xbox (GDK)


Xbox Live Helper Library, and Xbox
Services API's (XSAPI) Multiplayer
Manager (MPM) together, meeting
Xbox Live requirements. It also shows
how to send game invites and join a
session.

See also
Party SDKs
Party overview
Getting started with Party
Recipes
5/24/2022 • 2 minutes to read • Edit Online

This collection of examples shows familiar patterns and mechanics implemented using PlayFab.

Player retention
Daily Prize Wheel - Give players a randomized gift every day, based on the values on a "Prize Wheel".
Progressive Reward System - Players that sign in consecutively over several days are granted an item,
depending on how long their login streak is.

User acquisition
Referral Code Bonus - Generate and send codes to friends that they can redeem and unlock a bonus for both
the referrer and themselves.
Cross-Promotional Rewards - Reward players participating in more than one of your games.

Monetization
Regenerating Currency Mechanic - A play-limiting mechanic (similar to Candy Crush lives), that slowly refills
to a maximum over time.

See also
General PlayFab samples
Multiplayer Servers samples
Party samples
SDK Generator
5/24/2022 • 2 minutes to read • Edit Online

Our SDK Generator provides everything you need to build your own SDK. Internally, we use this generator to
automate our many SDKs.
We have made the project open-source, to aide others who are looking for a language, platform or environment
that is not currently supported.
Download Links:
Download Source Code
Download PlayFab SDK Generator
Usage Guide
SDK Generator quickstart
5/24/2022 • 3 minutes to read • Edit Online

The SDK Generator is a node.js-based program that takes a JSON description of the PlayFab API, and uses it to
generate out all the different SDKs that must be kept up to date. The SDK Generator project also contains the
sources for all PlayFab SDKs on all platforms. If you want to make a change in an SDK, this is where the change
has to go.
Before you can call any PlayFab API, you must have a PlayFab developer account.

Prerequisites
1. Any recent MS-Windows Operating System.
2. You must have Node.js installed: https://nodejs.org/
The location of node.exe must be in your PATH environment variable. Default: C:\Program Files
(x86)\nodejs\
It is highly suggested that you install Node.js tools for Visual
Studio: https://beta.visualstudio.com/vs/node-js/.
3. SdkGenerator requires several PlayFab repositories, cloned to your local machine, as sibling folders to
SdkGenerator .
<parent-folder>/SdkGenerator = <https://github.com/PlayFab/SDKGenerator> (you're looking at it)
<parent-folder>/sdks/<targetSDK> - For every SDK you want to generate, you should git-clone the
PlayFab repository for that target into the "sdks" sub-folder first. In many cases, there are required
files in the repo which are not generated.
4. SdkGenerator can be configured to read from other PlayFab repositories, cloned to your local machine, as
sibling folders to SdkGenerator.
<parent-folder>/API_Specs = <https://github.com/PlayFab/api_specs>

Usage instructions
If you have installed Node.js tools, then you can build any existing SDK from the Visual Studio
solution: https://github.com/PlayFab/SDKGenerator/blob/master/SDKGenerator.sln
Open the solution.
Set the Project Configuration to match the SDK you wish to build.
Build -> Build Solution .
There are many prebuilt scripts which can build each SDK
automatically: https://github.com/PlayFab/SDKGenerator/tree/master/SDKBuildScripts
Find the script that matches the SDK you wish to build (EX unity_build.bat).
Double-click that file.
If you want to build a new SDK, you may need to build a new .bat file using the instructions in the next section.
Finally, you must supply a list of targets to generate, and the directory to generate them to.
To manually invoke the generator, open a command line at the root of the project and type in a target. Each
target takes the form:
<targetName>=<targetOutputLocation>

Where <targetName> is one of the supported SDK targets, and <targetOutputLocation> is a path to a directory in
which to generate the SDK.

NOTE
Make sure there are no spaces between the arguments and the equals sign.

API -Spec location


You may optionally define exactly one location to read API-Spec information.
-apiSpecPath []
If the -apiSpecPath switch is defined without a path, this defaults to ../API_Specs (relative
path, sibling to SdkGenerator repo location).
-apiSpecGitUrl []
If the -apiSpecGitUrl switch is defined without a URL, this defaults to
<https://raw.githubusercontent.com/PlayFab/API_Specs/master/>
Reads API_Specs directly from a GitHub repository.
-apiSpecPfUrl []
If the -apiSpecPfUrl switch is defined without a URL, this defaults to
<https://www.playfabapi.com/apispec/>
Reads API_Specs directly from the PlayFab API Server.
Flags are optional, and can be used to generate console APIs.

Building a new SDK


Setting up a new target in the SdkGenerator is fairly simple. This example has been added to the SdkGenerator
for reference: https://github.com/PlayFab/SDKGenerator/tree/master/targets/newTarget.
Add a new sub-folder in SdkGenerator/Targets.
Add a "make.js" file to your new target.
Implement makeClientAPI2 , makeServerAPI , and/or makeCombinedAPI in the file, as shown in
the NewTarget Example.
Optionally, you may use template files and source files, as described in the NewTarget example.
Add a new bat-file to generate your sdk in SdkGenerator/SDKBuildScripts.
PlayFab sometimes accepts submissions for new SDKs. This process is extensive, and it has to be integrated with
our automated build and testing system. For more information contact us on the forums.

Troubleshooting
For a complete list of available APIs, check out the API References.
Contact us
We love to hear from our developer community! Do you have ideas on how we can make our products and
services better?
Our Developer Success Team can assist with answering any questions as well as process any feedback you have
about PlayFab services.
Forums, Support and Knowledge Base
Postman (REST)
5/24/2022 • 2 minutes to read • Edit Online

Our Postman collection provides JSON mapping to our API that is directly importable into Postman. This is the
one of the fastest ways to get started testing PlayFab. When imported into Postman, you will get a full
integration that supports multiple environment configurations.
Every API call imported is set up with variables in URLs and parameters, making it easy for you to switch
between titles. To get started, check out our Quickstart.
Quickstart: PlayFab REST API collection for Postman
5/24/2022 • 3 minutes to read • Edit Online

Get started with the PlayFab REST API collection for Postman. Follow steps to install the package and try out
example code for basic tasks. PlayFab is a complete backend platform for live games. Use the PlayFab REST API
collection for Postman to:
Get an entity token
Add/modify/delete entities in a title
Configure title content
API reference documentation | PlayFab Postman Collection GitHub repository

Prerequisites
A PlayFab developer account
The Postman native app
An OS running running TLS 1.2 or higher (Windows support for TLS 1.2)
Adding PlayFab Collections
Select Impor t (top left of the window)

Select Impor t From Link


Paste the following link into the URL text box and select Impor t
https://raw.githubusercontent.com/PlayFab/PostmanCollection/master/playfabV2.json
If you are trying to download the beta SDK, go to the playfabV2.json file in the Postman Beta
GitHub repository
Select View Raw

Copy the URL from the browser, paste the link into the URL text box and select Impor t
You should now see the PlayFab Postman SDK under the Collections tab (top left of the window)
Adding Environment Variables
Select Manage Environments (cog icon at the top right of the window)

Select Add to create a new environment


Name your environment - we recommend "[titleId] - Test Environment"

NOTE
You can find your title id by logging into Game Manager and copying the hex value below your title name on the My
Studios and Titles main page.

Add the following 3 variables to the environment:


VA RIA B L E IN IT IA L VA L UE C URREN T VA L UE

TitleId [titleId] [titleId]

SecretKey [secretKey] [secretKey]

EntityToken

NOTE
You can learn more about title secret keys and where to find them in the Secret Key Management documentation.

When finished, select Add (or Update) to save your new environment
Exit out of the Manage Environment window and select the environment dropdown to switch to your
new environment (top right of the window)
Getting a Title Entity Token
One way to interact with PlayFab's Entity Programming Model is to get a Title Entity Token. This can be useful if
you want to make changes to title config data, or if you want to make adjustments to a large amount of players:
Under the PlayFab Collections folder, expand the Authentication namespace and select
GetEntityToken

Under Headers , uncheck X-Authorization

Select Send
Set the returned entity token to your EntityToken environment variable
In the response, highlight the EntityToken string (don't forget the '==')
Right-click and select Set: [Environment] for your new environment
Select EntityToken
NOTE
Entity tokens expire after 24 hours . Afterwards, you need to re-run GetEntityToken to get a new entity token and
update your environment variable

Getting a Title_Player_Account Entity Token


Another way to interact with PlayFab's Entity Programming Model is to get a Title_Player_Account Entity Token.
This is useful if you want to make changes to a single player:
Under the PlayFab Collections folder, expand the Client namespace and select LoginWithCustomID
Under Body , change the CreateAccount value from false to true
Select Send
Set the returned entity token to your EntityToken environment variable
In the response, highlight the EntityToken string
Right-click and select Set: [Environment] for your new environment
Select EntityToken

Troubleshooting
Title id / secret key mismatch
If you are trying to get a title entity token and receiving a 401: Unauthorized error, make sure the title
id and secret keys are correct by logging into Game Manager
Expired entity token
If you previously obtained an entity token and are unsuccessfully attempting to call other APIs, your
entity token might be expired. Get another entity token, save it into the EntityToken environment
variable, and attempt to call the previous API again
Incorrect entity token type
There are different types of entities (see Available built-in entity types). Different APIs allow different
entity types - for example, you might be attempting to call GetLanguageList with a
title_player_account entity token instead of a title entity token
Incorrect environment:
Make sure you are using the proper environment by checking the environment dropdown (top right
of the window)

Next Steps
You now have an entity token to pass into other API calls to start setting up your PlayFab title.
Getting Started: Developers >
PlayFab Quickstarts >
API References >

You might also like