NAV Navbar
C# C++ Objective-C Java JavaScript Cloud Code Raw
  • Introduction
  • BrainCloudWrapper
  • Client API
  • Cloud Code
  • Server to Server (S2S)
  • Appendix
  • Introduction

    brainCloud Architecture

    What is brainCloud?

    brainCloud is a ready-made back-end platform for the development of feature-rich games, apps and things. brainCloud provides the features you need – along with comprehensive tools to support your team during development, testing and user support.

    brainCloud consists of:

    SDK libraries

    There are custom brainCloud libraries for several languages including:

    Engine Support

    brainCloud supports the most popular gaming engines, including:

    BrainCloudWrapper

    // Unity
    
    //Note: Ensure of have selected your app using the brainCloud Unity Plugin
    
    using UnityEngine;
    
    public class BCConfig : MonoBehaviour {
    
        private BrainCloudWrapper _bc;
    
        public BrainCloudWrapper GetBrainCloud()
        {
            return _bc;
        }   
    
        void Awake ()
        {
            DontDestroyOnLoad(gameObject);
            _bc = gameObject.AddComponent<BrainCloudWrapper>();
    
            _bc.WrapperName = gameObject.name;    // Optional: Set a wrapper name
            _bc.Init();      // Init data is taken from the brainCloud Unity Plugin     
        }
    }
    
    
    // C#
    _bc = new BrainCloudWrapper("_mainWrapper");
    
    _bc = new BrainCloudWrapper("_mainWrapper");
    
    _bc = new BrainCloudWrapper("_mainWrapper");
    
    _bc = [[BrainCloudWrapper alloc] init: @"_mainWrapper"]
    
    _bc = new BrainCloudWrapper("_mainWrapper");
    

    The BrainCloudWrapper class provides an easier way for developers to handle user authentication when they are getting started with the authentication system. This includes persisting authentication data between application runs.

    By using the wrapper authentication methods, the anonymous and profile IDs will be automatically persisted upon successful authentication. When authenticating, any stored anonymous/profile IDs will be sent to the server. This strategy is useful when using Anonymous authentication.

    Note - you should initialize the wrapper before using it. It will in turn initialize the brainCloud client for you - don't do both!

    Parameters
    Parameter Description
    wrapperName Distincts saved wrapper data. Use when using more than one instance of brainCloud

    AuthenticateAnonymous

    _bc->authenticateAnonymous(this);
    
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Success] {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Failed] {0}  {1}  {2}", status, code, error));
    };
    
    _bc.AuthenticateAnonymous(successCallback, failureCallback);
    
    _bc.authenticateAnonymous();
    
    [_bc authenticateAnonymous:successBlock
          errorCompletionBlock:failureBlock
                      cbObject:nil];
    
    _bc.authenticateAnonymous(result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": {
            "vcPurchased": 0,
            "xpCapped": false,
            "experiencePoints": 230,
            "sent_events": [
            ],
            "playerSessionExpiry": 1200,
            "playerName": "Jimmy",
            "vcClaimed": 0,
            "parentProfileId": null,
            "rewards": {
                "rewardDetails": {},
                "rewards": {},
                "currency": {}
            },
            "loginCount": 23,
            "server_time": 1445545791711,
            "experienceLevel": 0,
            "entities": [
            ],
            "incoming_events": [
            ],
            "currency": {
                "gold": {
                    "purchased": 0,
                    "balance": 0,
                    "consumed": 0,
                    "awarded": 0
                }
            },
            "statistics": {
                "deaths": 0,
                "kills": 0
            },
            "abTestingId": 78,
            "id": "47037fc9-ca7b-4f61-a71f-e5a37b0e8a03",
            "sessionId": "bg6qf38p2btl0o825s99385nd1",
            "profileId": "47037fc9-ca7b-4f61-a71f-e5a37b0e8a03",
            "newUser": "false"
        }
    }
    

    Authenticate a user anonymously with brainCloud - used for apps that don't want to bother the user to login, or for users who are sensitive to their privacy.

    Service Operation
    "authenticationV2" "AUTHENTICATE"
    Error returns
    Show Example Error Handling {}
    public void FailureCallback(int statusCode, int reasonCode, string statusMessage, object cbObject) {
        switch (reasonCode) {
            case ReasonCodes.MISSING_IDENTITY_ERROR: {  // Identity does not match any profile
    
                // Reset Profile ID and re-authenticate
                _bc.ResetStoredProfileId();
                _bc.AuthenticateAnonymous();
                break;
            }
            case ReasonCodes.SWITCHING_PROFILES: {  // Identity belongs to a different profile
    
                // Reset Profile ID and Anonymous id, and then re-authenticate
                _bc.ResetStoredProfileId();
                _bc.ResetStoredAnonymousId();
                _bc.AuthenticateAnonymous();
                break;
            }
            default: { // Uncaught reasonCode  // Uncaught reasonCode
    
                // Log the error for debugging later
                // ...
                break;
            }
        }
    }
    
    Code Name Description
    40206 MISSING_IDENTITY_ERROR Both an anonymousId and profileId were provided for authentication - but the anonymousId doesn't exist on the server. The profileId may or may not exist. It is possible that the user account was deleted via the Design Portal. The proper recourse is to reset the stored profile id, and re-authenticate. [There is no need to delete the anonymousId since it doesn't exist on the server anyway.]
    40207 SWITCHING_PROFILES This means that the anonymousId provided does point to a profile, but not the same one that was saved in the client. This fails the anonymous security check. For any other authentication type, this might indicate that the user wants to switch accounts (thus the name of the error constant). For anonymous, the only response is to reset both the stored anonymousId and profileId, and then re-authenticate.
    40217 UNKNOWN_AUTH_ERROR An unknown error has occurred during authentication

    AuthenticateEmailPassword

    string email = "my_Email@getbraincloud.com";
    string password = "MyP@ssW0rd!";
    bool forceCreate = true;
    
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Success] {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Failed] {0}  {1}  {2}", status, code, error));
    };
    _bc.AuthenticateEmailPassword(
        email, password, forceCreate, successCallback, failureCallback);
    
    const char* email = "my_Email@getbraincloud.com";
    const char* password = "MyP@ssW0rd!";
    bool forceCreate = true;
    
    _bc->authenticateEmailPassword(email, password, forceCreate, this);
    
    NSString* email = @"my_Email@getbraincloud.com";
    NSString* password = @"MyP@ssW0rd!";
    bool forceCreate = true;
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [_bc authenticateEmailPassword:email
                         password:password
                      forceCreate:forceCreate
                  completionBlock:successBlock
             errorCompletionBlock:failureBlock
                         cbObject:nil];
    
    String email = "my_Email@getbraincloud.com";
    String password = "MyP@ssW0rd!";
    boolean forceCreate = true;
    
    _bc.authenticateEmailPassword(
        email,
        password,
        forceCreate,
        this);
    
    var email = "my_Email@getbraincloud.com";
    var password = "MyP@ssW0rd!";
    var forceCreate = true;
    
    _bc.authenticateEmailPassword(email, password, forceCreate, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": {
            "vcPurchased": 0,
            "xpCapped": false,
            "experiencePoints": 230,
            "sent_events": [
            ],
            "playerSessionExpiry": 1200,
            "playerName": "Jimmy",
            "vcClaimed": 0,
            "parentProfileId": null,
            "rewards": {
                "rewardDetails": {},
                "rewards": {},
                "currency": {}
            },
            "loginCount": 23,
            "server_time": 1445545791711,
            "experienceLevel": 0,
            "entities": [
            ],
            "incoming_events": [
            ],
            "currency": {
                "gold": {
                    "purchased": 0,
                    "balance": 0,
                    "consumed": 0,
                    "awarded": 0
                }
            },
            "statistics": {
                "deaths": 0,
                "kills": 0
            },
            "abTestingId": 78,
            "id": "47037fc9-ca7b-4f61-a71f-e5a37b0e8a03",
            "sessionId": "bg6qf38p2btl0o825s99385nd1",
            "profileId": "47037fc9-ca7b-4f61-a71f-e5a37b0e8a03",
            "newUser": "false"
        }
    }
    

    Authenticate the user with a custom Email and Password. Note that the client app is responsible for collecting (and storing) the e-mail and potentially password (for convenience) in the client data. For the greatest security, force the user to re-enter their password at each login (or at least give them that option).

    Service Operation
    "authenticationV2" "AUTHENTICATE"
    Method Parameters
    Parameter Description
    email The e-mail address of the user
    password The password of the user
    forceCreate Should a new profile be created for this user if the account does not exist?
    Error returns
    Show Example Error Handling {}
    public void FailureCallback(int statusCode, int reasonCode, string statusMessage, object cbObject) {
        switch (reasonCode) {
            case ReasonCodes.MISSING_IDENTITY_ERROR: {  // Identity does not exist (and client has orphaned profileId)
    
                // Reset profileId and re-authenticate
                _bc.ResetStoredProfileId();
                _bc.AuthenticateUniversal(userId, password, true);
                break;
            }
            case ReasonCodes.SWITCHING_PROFILES: {  // Identity belongs to a different profile
    
                // [Optional] Prompt user to confirm that they wish to switch accounts?
    
                // Reset profileId and re-authenticate
                _bc.ResetStoredProfileId();
                _bc.AuthenticateUniversal(userId, password, forceCreate);
                break;
            }
            case ReasonCodes.MISSING_PROFILE_ERROR: {  // Identity does not exist
    
                // The account doesn't exist - create it now.
                _bc.AuthenticateUniversal(userId, password, true);
                break;
            }
            case ReasonCodes.TOKEN_DOES_NOT_MATCH_USER: {  // Wrong password
    
                // Display a dialog telling the user that the password provided was invalid,
                // and invite them to re-enter the password.
                // ...
                break;
            }
            default: { // Uncaught reasonCode
    
                // Log the error for debugging later
                // ...
                break;
            }
        }
    }
    
    Code Name Description
    40206 MISSING_IDENTITY_ERROR The identity does not exist on the server and forceCreate was false [and a profileId was provided - otherwise 40208 would have been returned]. Will also occur when forceCreate is true and a saved [and unrelated] profileId is provided. The error handler should reset the stored profile id (if there is one) and re-authenticate, setting forceCreate to true to create a new account. A common cause of this error is deleting the user's account via the Design Portal.
    40207 SWITCHING_PROFILES Indicates that the identity credentials are valid, and the saved profileId is valid, but the identity is not associated with the profileId. This may indicate that the user wants to switch accounts in the app. Often an app will pop-up a dialog confirming that the user wants to switch accounts, and then reset the stored profileId and call authenticate again.
    40208 MISSING_PROFILE_ERROR Returned when the identity cannot be located, no profileId is provided, and forceCreate is false. The normal response is to call Authenticate again with forceCreate set to true.
    40217 UNKNOWN_AUTH_ERROR An unknown error has occurred during authentication.
    40307 TOKEN_DOES_NOT_MATCH_USER The user credentials don't match (i.e. incorrect password).

    AuthenticateExternal

    string userId = "externalId";
    string token = "externalTokenOrPassword";
    string externalAuthName = "nameOfExternalAuthService";
    bool forceCreate = true;
    
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Success] {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Failed] {0}  {1}  {2}", status, code, error));
    };
    _bc.AuthenticateExternal(
        userId, token, externalAuthName, forceCreate,
        successCallback, failureCallback);
    
    const char* userId = "externalId";
    const char* token = "externalTokenOrPassword";
    const char* externalAuthName = "nameOfExternalAuthService";
    
    _bc->authenticateExternal(
        userId,
        token,
        externalAuthName,
        true,
        this);
    
    NSString* authId = @"1234";
    NSString* authToken = @"1234-1234-1234-1234";
    NSString* externalAuthName = @"externalSystem";
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [_bc authenticateExternal:authId
             authenticationToken:authToken
      externalAuthenticationName:externalAuthName
                     forceCreate:true
                 completionBlock:successBlock
            errorCompletionBlock:failureBlock
                        cbObject:nil];
    
    String userId = "externalId";
    String token = "externalTokenOrPassword";
    String externalAuthName = "nameOfExternalAuthService";
    
    _bc.authenticateExternal(
        userId,
        token,
        externalAuthName,
        true,
        this);
    
    var userId = "externalId";
    var token = "externalTokenOrPassword";
    var externalAuthName = "nameOfExternalAuthService";
    var forceCreate = true;
    
    _bc.authenticateExternal(userId, token, externalAuthName, forceCreate, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": {
            "vcPurchased": 0,
            "xpCapped": false,
            "experiencePoints": 230,
            "sent_events": [
            ],
            "playerSessionExpiry": 1200,
            "playerName": "Jimmy",
            "vcClaimed": 0,
            "parentProfileId": null,
            "rewards": {
                "rewardDetails": {},
                "rewards": {},
                "currency": {}
            },
            "loginCount": 23,
            "server_time": 1445545791711,
            "experienceLevel": 0,
            "entities": [
            ],
            "incoming_events": [
            ],
            "currency": {
                "gold": {
                    "purchased": 0,
                    "balance": 0,
                    "consumed": 0,
                    "awarded": 0
                }
            },
            "statistics": {
                "deaths": 0,
                "kills": 0
            },
            "abTestingId": 78,
            "id": "47037fc9-ca7b-4f61-a71f-e5a37b0e8a03",
            "sessionId": "bg6qf38p2btl0o825s99385nd1",
            "profileId": "47037fc9-ca7b-4f61-a71f-e5a37b0e8a03",
            "newUser": "false"
        }
    }
    

    Authenticate the user via cloud code (which in turn validates the supplied credentials against an external system). This allows the developer to extend brainCloud authentication to support other backend authentication systems.

    Service Operation
    "authenticationV2" "AUTHENTICATE"
    Method Parameters
    Parameter Description
    userId The userId
    token The user token (password etc)
    externalAuthName The name of the custom authentication type (linked to a cloud script that performs authentication). Configured via the Design | Authentication | External page of the Design Portal.
    forceCreate Should a new profile be created for this user if the account does not exist?
    Error returns
    Code Name Description
    40206 MISSING_IDENTITY_ERROR The identity does not exist on the server and forceCreate was false [and a profileId was provided - otherwise 40208 would have been returned]. Will also occur when forceCreate is true and a saved [but un-associated] profileId is provided. The error handler should reset the stored profile id (if there is one) and re-authenticate, setting forceCreate to true to create a new account. A common cause of this error is deleting the user's account via the Design Portal.
    40207 SWITCHING_PROFILES Indicates that the identity credentials are valid, and the saved profileId is valid, but the identity is not associated with the provided profileId. This may indicate that the user wants to switch accounts in the app. Often an app will pop-up a dialog confirming that the user wants to switch accounts, and then reset the stored profileId and call authenticate again.
    40208 MISSING_PROFILE_ERROR Returned when the identity cannot be located, no profileId is provided, and forceCreate is false. The normal response is to call Authenticate again with forceCreate set to true.
    40217 UNKNOWN_AUTH_ERROR An unknown error has occurred during authentication.
    40307 TOKEN_DOES_NOT_MATCH_USER The user credentials don't match (according to the 3rd party system). May also indicate an issue with the external authentication script.

    AuthenticateFacebook

    string facebookId = "userFacebookId";
    string facebookToken = "tokenFromFacebook";
    bool forceCreate = true;
    
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Success] {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Failed] {0}  {1}  {2}", status, code, error));
    };
    
    _bc.AuthenticateFacebook(
        facebookId, facebookToken, forceCreate,
        successCallback, failureCallback);
    
    const char* facebookId = "userFacebookId";
    const char* facebookToken = "tokenFromFacebook";
    bool forceCreate = true;
    
    _bc->authenticateFacebook(
        facebookId,
        facebookToken,
        forceCreate,
        this);
    
    NSString* facebookId = @"userFacebookId";
    NSString* facebookToken = @"tokenFromFacebook";
    bool forceCreate = true;
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [_bc authenticateExternal:facebookId
             authenticationToken:facebookToken
                     forceCreate:forceCreate
                 completionBlock:successBlock
            errorCompletionBlock:failureBlock
                        cbObject:nil];
    
    String facebookId = "userFacebookId";
    String facebookToken = "tokenFromFacebook";
    boolean forceCreate = true;
    this; // implements IServerCallback
    
    _bc.authenticateFacebook(facebookId, facebookToken, forceCreate, this);
    
    public void serverCallback(ServiceName serviceName, ServiceOperation serviceOperation, JSONObject jsonData)
    {
        System.out.print(String.format("Success | %s", jsonData.toString()));
    }
    public void serverError(ServiceName serviceName, ServiceOperation serviceOperation, int statusCode, int reasonCode, String jsonError)
    {
        System.out.print(String.format("Failed | %d %d %s", statusCode,  reasonCode, jsonError.toString()));
    }
    
    var facebookId = "userFacebookId";
    var token = "tokenFromFacebook";
    var forceCreate = true;
    
    _bc.authenticateFacebook(facebookId, token, forceCreate, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": {
            "vcPurchased": 0,
            "xpCapped": false,
            "experiencePoints": 230,
            "sent_events": [
            ],
            "playerSessionExpiry": 1200,
            "playerName": "Jimmy",
            "vcClaimed": 0,
            "parentProfileId": null,
            "rewards": {
                "rewardDetails": {},
                "rewards": {},
                "currency": {}
            },
            "loginCount": 23,
            "server_time": 1445545791711,
            "experienceLevel": 0,
            "entities": [
            ],
            "incoming_events": [
            ],
            "currency": {
                "gold": {
                    "purchased": 0,
                    "balance": 0,
                    "consumed": 0,
                    "awarded": 0
                }
            },
            "statistics": {
                "deaths": 0,
                "kills": 0
            },
            "abTestingId": 78,
            "id": "47037fc9-ca7b-4f61-a71f-e5a37b0e8a03",
            "sessionId": "bg6qf38p2btl0o825s99385nd1",
            "profileId": "47037fc9-ca7b-4f61-a71f-e5a37b0e8a03",
            "newUser": "false"
        }
    }
    

    Authenticate the user with brainCloud using their Facebook Credentials.

    Service Operation
    "authenticationV2" "AUTHENTICATE"
    Method Parameters
    Parameter Description
    facebookId The Facebook ID of the user
    facebookToken The validated token from the Facebook SDK
    forceCreate Should a new profile be created for this user if the account does not exist?
    Error returns
    Code Name Description
    40206 MISSING_IDENTITY_ERROR The identity does not exist on the server and forceCreate was false [and a profileId was provided - otherwise 40208 would have been returned]. Will also occur when forceCreate is true and a saved [but un-associated] profileId is provided. The error handler should reset the stored profile id (if there is one) and re-authenticate, setting forceCreate to true to create a new account. A common cause of this error is deleting the user's account via the Design Portal.
    40207 SWITCHING_PROFILES Indicates that the identity credentials are valid, and the saved profileId is valid, but the identity is not associated with the provided profileId. This may indicate that the user wants to switch accounts in the app. Often an app will pop-up a dialog confirming that the user wants to switch accounts, and then reset the stored profileId and call authenticate again.
    40208 MISSING_PROFILE_ERROR Returned when the identity cannot be located, no profileId is provided, and forceCreate is false. The normal response is to call Authenticate again with forceCreate set to true.
    40217 UNKNOWN_AUTH_ERROR An unknown error has occurred during authentication.
    40307 TOKEN_DOES_NOT_MATCH_USER The user credentials are invalid (i.e. bad Facebook id / token). May also indicate that Facebook integration is not properly configured.

    AuthenticateGameCenter

    string gameCenterId = "userGameCenterId";
    bool forceCreate = true;
    
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Success] {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Failed] {0}  {1}  {2}", status, code, error));
    };
    _bc.AuthenticateGameCenter(
        gameCenterId, forceCreate,
        successCallback, failureCallback);
    
    const char* gameCenterId = "userGameCenterId";
    bool forceCreate = true;
    
    _bc->authenticateGameCenter(
        gameCenterId,
        forceCreate,
        this);
    
    NSString* gameCenterID = @"userGameCenterId";
    BOOL forceCreate = true;
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [_bc authenticateGameCenter:gameCenterID
                     forceCreate:forceCreate
                 completionBlock:successBlock
            errorCompletionBlock:failureBlock
                        cbObject:nil];
    
    // N/A
    
    var gameCenterId = "userGameCenterId";
    var forceCreate = true;
    
    _bc.authenticateGameCenter(gameCenterId, forceCreate, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": {
            "vcPurchased": 0,
            "xpCapped": false,
            "experiencePoints": 230,
            "sent_events": [
            ],
            "playerSessionExpiry": 1200,
            "playerName": "Jimmy",
            "vcClaimed": 0,
            "parentProfileId": null,
            "rewards": {
                "rewardDetails": {},
                "rewards": {},
                "currency": {}
            },
            "loginCount": 23,
            "server_time": 1445545791711,
            "experienceLevel": 0,
            "entities": [
            ],
            "incoming_events": [
            ],
            "currency": {
                "gold": {
                    "purchased": 0,
                    "balance": 0,
                    "consumed": 0,
                    "awarded": 0
                }
            },
            "statistics": {
                "deaths": 0,
                "kills": 0
            },
            "abTestingId": 78,
            "id": "47037fc9-ca7b-4f61-a71f-e5a37b0e8a03",
            "sessionId": "bg6qf38p2btl0o825s99385nd1",
            "profileId": "47037fc9-ca7b-4f61-a71f-e5a37b0e8a03",
            "newUser": "false"
        }
    }
    

    Authenticate the user using their Game Center ID.

    Service Operation
    "authenticationV2" "AUTHENTICATE"
    Method Parameters
    Parameter Description
    gameCenterId The player's game center ID (use the playerID property from the local GKPlayer object)
    forceCreate Should a new profile be created for this user if the account does not exist?
    Error returns
    Code Name Description
    40206 MISSING_IDENTITY_ERROR The identity does not exist on the server and forceCreate was false [and a profileId was provided - otherwise 40208 would have been returned]. Will also occur when forceCreate is true and a saved [but un-associated] profileId is provided. The error handler should reset the stored profile id (if there is one) and re-authenticate, setting forceCreate to true to create a new account. A common cause of this error is deleting the user's account via the design portal.
    40207 SWITCHING_PROFILES Indicates that the identity credentials are valid, and the saved profileId is valid, but the identity is not associated with the provided profileId. This may indicate that the user wants to switch accounts in the app. Often an app will pop-up a dialog confirming that the user wants to switch accounts, and then reset the stored profileId and call authenticate again.
    40208 MISSING_PROFILE_ERROR Returned when the identity cannot be located, no profileId is provided, and forceCreate is false. The normal response is to call Authenticate again with forceCreate set to true.
    40217 UNKNOWN_AUTH_ERROR An unknown error has occurred during authentication.
    40307 TOKEN_DOES_NOT_MATCH_USER The user credentials are invalid (i.e. bad gameCenterId)

    AuthenticateGoogle

    string googleId = "idFromGoogle";
    string googleToken = "authTokenFromGoogle";
    bool forceCreate = true;
    
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Success] {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Failed] {0}  {1}  {2}", status, code, error));
    };
    _bc.AuthenticateGoogle(
        googleId, googleToken, forceCreate,
        successCallback, failureCallback);
    
    const char* googleId = "idFromGoogle";
    const char* googleToken = "authTokenFromGoogle";
    bool forceCreate = true;
    
    _bc->authenticateGoogle(
        googleId, googleToken, forceCreate, this);
    
    NSString* googleId = @"idFromGoogle";
    NSString* googleToken = @"authTokenFromGoogle";
    BOOL forceCreate = true;
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [_bc authenticateGoogle:googleId
                          token:googleToken
                    forceCreate:forceCreate
                completionBlock:successBlock
           errorCompletionBlock:failureBlock
                       cbObject:nil];
    
    String googleId = "idFromGoogle";
    String googleToken = "authTokenFromGoogle";
    boolean forceCreate = true;
    this; // implements IServerCallback
    
    _bc.authenticateGoogle(
        googleId, googleToken, forceCreate, this);
    
    public void serverCallback(ServiceName serviceName, ServiceOperation serviceOperation, JSONObject jsonData)
    {
        System.out.print(String.format("Success | %s", jsonData.toString()));
    }
    public void serverError(ServiceName serviceName, ServiceOperation serviceOperation, int statusCode, int reasonCode, String jsonError)
    {
        System.out.print(String.format("Failed | %d %d %s", statusCode,  reasonCode, jsonError.toString()));
    }
    
    var googleId = "idFromGoogle";
    var googleToken = "authTokenFromGoogle";
    var forceCreate = true;
    
    _bc.authenticateGoogle(googleId, googleToken, forceCreate, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": {
            "vcPurchased": 0,
            "xpCapped": false,
            "experiencePoints": 230,
            "sent_events": [
            ],
            "playerSessionExpiry": 1200,
            "playerName": "Jimmy",
            "vcClaimed": 0,
            "parentProfileId": null,
            "rewards": {
                "rewardDetails": {},
                "rewards": {},
                "currency": {}
            },
            "loginCount": 23,
            "server_time": 1445545791711,
            "experienceLevel": 0,
            "entities": [
            ],
            "incoming_events": [
            ],
            "currency": {
                "gold": {
                    "purchased": 0,
                    "balance": 0,
                    "consumed": 0,
                    "awarded": 0
                }
            },
            "statistics": {
                "deaths": 0,
                "kills": 0
            },
            "abTestingId": 78,
            "id": "47037fc9-ca7b-4f61-a71f-e5a37b0e8a03",
            "sessionId": "bg6qf38p2btl0o825s99385nd1",
            "profileId": "47037fc9-ca7b-4f61-a71f-e5a37b0e8a03",
            "newUser": "false"
        }
    }
    

    Authenticate the user using a google user ID (email address) and google authentication token.

    Service Operation
    "authenticationV2" "AUTHENTICATE"
    Method Parameters
    Parameter Description
    googleId String representation of google+ userid (email)
    googleToken The authentication token derived via the google apis.
    forceCreate Should a new profile be created for this user if the account does not exist?
    Error returns
    Code Name Description
    40206 MISSING_IDENTITY_ERROR The identity does not exist on the server and forceCreate was false [and a profileId was provided - otherwise 40208 would have been returned]. Will also occur when forceCreate is true and a saved [but un-associated] profileId is provided. The error handler should reset the stored profile id (if there is one) and re-authenticate, setting forceCreate to true to create a new account. A common cause of this error is deleting the user's account via the Design Portal.
    40207 SWITCHING_PROFILES Indicates that the identity credentials are valid, and the saved profileId is valid, but the identity is not associated with the provided profileId. This may indicate that the user wants to switch accounts in the app. Often an app will pop-up a dialog confirming that the user wants to switch accounts, and then reset the stored profileId and call authenticate again.
    40208 MISSING_PROFILE_ERROR Returned when the identity cannot be located, no profileId is provided, and forceCreate is false. The normal response is to call Authenticate again with forceCreate set to true.
    40217 UNKNOWN_AUTH_ERROR An unknown error has occurred during authentication.
    40307 TOKEN_DOES_NOT_MATCH_USER The user credentials are invalid (i.e. googleId and googleToken are invalid). May also indicate that Google Integration is not properly configured.

    AuthenticateSteam

    string steamId = "userSteamId";
    string sessionTicket = "sessionTicketFromSteam";
    bool forceCreate = true;
    
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Success] {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Failed] {0}  {1}  {2}", status, code, error));
    };
    _bc.AuthenticateSteam(
        steamId, tisessionTicketcket, forceCreate,
        successCallback, failureCallback);
    
    const char* steamId = "userSteamId";
    const char* sessionTicket = "sessionTicketFromSteam";
    bool forceCreate = true;
    
    _bc->authenticateSteam(
        steamId, sessionTicket, forceCreate, this);
    
    NSString* userID = @"userSteamId";
    NSString* sessionticket = @"sessionTicketFromSteam";
    BOOL forceCreate = true;
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [_bc authenticateSteam:userID
                 sessionTicket:sessionticket
                   forceCreate:forceCreate
               completionBlock:successBlock
          errorCompletionBlock:failureBlock
                      cbObject:nil];
    
    Steam steamId = "userSteamId";
    Steam sessionTicket = "sessionTicketFromSteam";
    boolean forceCreate = true;
    this; // implements IServerCallback
    
    _bc.authenticateSteam(
        steamId, sessionTicket, forceCreate, this);
    
    var steamId = "userSteamId";
    var sessionTicket = "sessionTicketFromSteam";
    var forceCreate = true;
    
    _bc.authenticateSteam(steamId, sessionTicket, forceCreate, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": {
            "vcPurchased": 0,
            "xpCapped": false,
            "experiencePoints": 230,
            "sent_events": [
            ],
            "playerSessionExpiry": 1200,
            "playerName": "Jimmy",
            "vcClaimed": 0,
            "parentProfileId": null,
            "rewards": {
                "rewardDetails": {},
                "rewards": {},
                "currency": {}
            },
            "loginCount": 23,
            "server_time": 1445545791711,
            "experienceLevel": 0,
            "entities": [
            ],
            "incoming_events": [
            ],
            "currency": {
                "gold": {
                    "purchased": 0,
                    "balance": 0,
                    "consumed": 0,
                    "awarded": 0
                }
            },
            "statistics": {
                "deaths": 0,
                "kills": 0
            },
            "abTestingId": 78,
            "id": "47037fc9-ca7b-4f61-a71f-e5a37b0e8a03",
            "sessionId": "bg6qf38p2btl0o825s99385nd1",
            "profileId": "47037fc9-ca7b-4f61-a71f-e5a37b0e8a03",
            "newUser": "false"
        }
    }
    

    Authenticate the user using a steam userId and session ticket (without any validation on the userId).

    Service Operation
    "authenticationV2" "AUTHENTICATE"
    Method Parameters
    Parameter Description
    userId String representation of 64 bit steam ID
    sessionTicket The session ticket of the user (hex encoded)
    forceCreate Should a new profile be created for this user if the account does not exist?
    Error returns
    Code Name Description
    40206 MISSING_IDENTITY_ERROR The identity does not exist on the server and forceCreate was false [and a profileId was provided - otherwise 40208 would have been returned]. Will also occur when forceCreate is true and a saved [but un-associated] profileId is provided. The error handler should reset the stored profile id (if there is one) and re-authenticate, setting forceCreate to true to create a new account. A common cause of this error is deleting the user's account via the Design Portal.
    40207 SWITCHING_PROFILES Indicates that the identity credentials are valid, and the saved profileId is valid, but the identity is not associated with the provided profileId. This may indicate that the user wants to switch accounts in the app. Often an app will pop-up a dialog confirming that the user wants to switch accounts, and then reset the stored profileId and call authenticate again.
    40208 MISSING_PROFILE_ERROR Returned when the identity cannot be located, no profileId is provided, and forceCreate is false. The normal response is to call Authenticate again with forceCreate set to true.
    40217 UNKNOWN_AUTH_ERROR An unknown error has occurred during authentication.
    40307 TOKEN_DOES_NOT_MATCH_USER The user credentials are invalid (i.e. bad Steam userId and/or sessionTicket). May also indicate that Steam Integration is not properly configured.

    AuthenticateTwitter

    string twitterId = "userTwitterId";
    string token = "userAuthToken";
    string secret = "secretFromTwitterApi";
    bool forceCreate = true;
    
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Success] {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Failed] {0}  {1}  {2}", status, code, error));
    };
    _bc.AuthenticateTwitter(
        twitterId, token, secret, forceCreate,
        successCallback, failureCallback);
    
    const char* twitterId = "userTwitterId";
    const char* token = "userAuthToken";
    const char* secret = "secretFromTwitterApi";
    
    _bc->authenticateTwitter(
        twitterId, token, secret, true, this);
    
    NSString* twitterId = @"userTwitterId";
    NSString* token = @"userAuthToken";
    NSString* secret = @"secretFromTwitterApi";
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [_bc authenticateTwitter:userID
                          token:token
                         secret:secret
                    forceCreate:true
                completionBlock:successBlock
           errorCompletionBlock:failureBlock
                       cbObject:nil];
    
    String twitterId = "userTwitterId";
    String token = "userAuthToken";
    String secret = "secretFromTwitterApi";
    boolean forceCreate = true;
    this; // implements IServerCallback
    
    _bc.authenticateTwitter(
        twitterId, token, secret, forceCreate, this);
    
    var twitterId = "userTwitterId";
    var token = "userAuthToken";
    var secret = "secretFromTwitterApi";
    var forceCreate = true;
    
    _bc.authenticateTwitter(twitterId, token, secret, forceCreate, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": {
            "vcPurchased": 0,
            "xpCapped": false,
            "experiencePoints": 230,
            "sent_events": [
            ],
            "playerSessionExpiry": 1200,
            "playerName": "Jimmy",
            "vcClaimed": 0,
            "parentProfileId": null,
            "rewards": {
                "rewardDetails": {},
                "rewards": {},
                "currency": {}
            },
            "loginCount": 23,
            "server_time": 1445545791711,
            "experienceLevel": 0,
            "entities": [
            ],
            "incoming_events": [
            ],
            "currency": {
                "gold": {
                    "purchased": 0,
                    "balance": 0,
                    "consumed": 0,
                    "awarded": 0
                }
            },
            "statistics": {
                "deaths": 0,
                "kills": 0
            },
            "abTestingId": 78,
            "id": "47037fc9-ca7b-4f61-a71f-e5a37b0e8a03",
            "sessionId": "bg6qf38p2btl0o825s99385nd1",
            "profileId": "47037fc9-ca7b-4f61-a71f-e5a37b0e8a03",
            "newUser": "false"
        }
    }
    

    Authenticate the user using a Twitter user ID, authentication token, and secret from Twitter.

    Service Operation
    "authenticationV2" "AUTHENTICATE"
    Method Parameters
    Parameter Description
    userId String representation of Twitter user ID
    token The authentication token derived via the Twitter APIs
    secret The secret given when attempting to link with Twitter
    forceCreate Should a new profile be created for this user if the account does not exist?
    Error returns
    Code Name Description
    40206 MISSING_IDENTITY_ERROR The identity does not exist on the server and forceCreate was false [and a profileId was provided - otherwise 40208 would have been returned]. Will also occur when forceCreate is true and a saved [but un-associated] profileId is provided. The error handler should reset the stored profile id (if there is one) and re-authenticate, setting forceCreate to true to create a new account. A common cause of this error is deleting the user's account via the Design Portal.
    40207 SWITCHING_PROFILES Indicates that the identity credentials are valid, and the saved profileId is valid, but the identity is not associated with the provided profileId. This may indicate that the user wants to switch accounts in the app. Often an app will pop-up a dialog confirming that the user wants to switch accounts, and then reset the stored profileId and call authenticate again.
    40208 MISSING_PROFILE_ERROR Returned when the identity cannot be located, no profileId is provided, and forceCreate is false. The normal response is to call Authenticate again with forceCreate set to true.
    40217 UNKNOWN_AUTH_ERROR An unknown error has occurred during authentication.
    40307 TOKEN_DOES_NOT_MATCH_USER The user credentials are invalid (i.e. bad Twitter userId / token / secret). May also indicate that Twitter integration is not properly configured.

    AuthenticateUniversal

    string userId = "MyUserName_007";
    string password = "MyP@ssW0rd!";
    bool forceCreate = true;
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Success] {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Failed] {0}  {1}  {2}", status, code, error));
    };
    
    _bc.AuthenticateUniversal(userId, password, forceCreate, successCallback, failureCallback);
    
    const char* userId = "MyUserName_007";
    const char* password = "MyP@ssW0rd!";
    bool forceCreate = true;
    
    _bc->authenticateUniversal(userId, password, forceCreate, this);
    
    NSString* userId = @"MyUserName_007";
    NSString* password = @"MyP@ssW0rd!";
    bool forceCreate = true;
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [_bc authenticateUniversal:userId
                   password:password
                forceCreate:forCreate
            completionBlock:successBlock
       errorCompletionBlock:failureBlock
                   cbObject:nil];
    
    String userId = "MyUserName_007";
    String password = "MyP@ssW0rd!";
    boolean forceCreate = true;
    this; // implements IServerCallback
    
    _bc.authenticateUniversal(userId, password, forceCreate, this);
    
    public void serverCallback(ServiceName serviceName, ServiceOperation serviceOperation, JSONObject jsonData)
    {
        System.out.print(String.format("Success | %s", jsonData.toString()));
    }
    public void serverError(ServiceName serviceName, ServiceOperation serviceOperation, int statusCode, int reasonCode, String jsonError)
    {
        System.out.print(String.format("Failed | %d %d %s", statusCode,  reasonCode, jsonError.toString()));
    }
    
    var userId = "MyUserName_007";
    var password = "MyP@ssW0rd!";
    var forceCreate = true;
    
    _bc.authenticateUniversal(userId, password, forceCreate, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": {
            "vcPurchased": 0,
            "xpCapped": false,
            "experiencePoints": 230,
            "sent_events": [
            ],
            "playerSessionExpiry": 1200,
            "playerName": "Jimmy",
            "vcClaimed": 0,
            "parentProfileId": null,
            "rewards": {
                "rewardDetails": {},
                "rewards": {},
                "currency": {}
            },
            "loginCount": 23,
            "server_time": 1445545791711,
            "experienceLevel": 0,
            "entities": [
            ],
            "incoming_events": [
            ],
            "currency": {
                "gold": {
                    "purchased": 0,
                    "balance": 0,
                    "consumed": 0,
                    "awarded": 0
                }
            },
            "statistics": {
                "deaths": 0,
                "kills": 0
            },
            "abTestingId": 78,
            "id": "47037fc9-ca7b-4f61-a71f-e5a37b0e8a03",
            "sessionId": "bg6qf38p2btl0o825s99385nd1",
            "profileId": "47037fc9-ca7b-4f61-a71f-e5a37b0e8a03",
            "newUser": "false"
        }
    }
    

    Universal authentication allows the developer to pass in any user/password string combination. As with all authentication methods, if the create new profile flag is specified as false, the authentication will fail if the user/password combination does not match a user in the database.

    Service Operation
    "authenticationV2" "AUTHENTICATE"
    Method Parameters
    Parameter Description
    userId The user's ID.
    password The password of the user.
    forceCreate Should a new profile be created for this user if the account does not exist?
    Error returns
    Show Example Error Handling {}
    public void FailureCallback(int statusCode, int reasonCode, string statusMessage, object cbObject) {
        switch (reasonCode) {
            case ReasonCodes.MISSING_IDENTITY_ERROR: {  // Identity does not exist (and client has orphaned profileId)
    
                // Reset profileId and re-authenticate
                _bc.ResetStoredProfileId();
                _bc.AuthenticateUniversal(userId, password, true);
                break;
            }
            case ReasonCodes.SWITCHING_PROFILES: {  // Identity belongs to a different profile
    
                // [Optional] Prompt user to confirm that they wish to switch accounts?
    
                // Reset profileId and re-authenticate
                _bc.ResetStoredProfileId();
                _bc.AuthenticateUniversal(userId, password, forceCreate);
                break;
            }
            case ReasonCodes.MISSING_PROFILE_ERROR: {  // Identity does not exist
    
                // The account doesn't exist - create it now.
                _bc.AuthenticateUniversal(userId, password, true);
                break;
            }
            case ReasonCodes.TOKEN_DOES_NOT_MATCH_USER: {  // Wrong password
    
                // Display a dialog telling the user that the password provided was invalid,
                // and invite them to re-enter the password.
                // ...
                break;
            }
            default: { // Uncaught reasonCode
    
                // Log the error for debugging later
                // ...
                break;
            }
        }
    }
    
    Code Name Description
    40206 MISSING_IDENTITY_ERROR The identity does not exist on the server and forceCreate was false [and a profileId was provided - otherwise 40208 would have been returned]. Will also occur when forceCreate is true and a saved [and unrelated] profileId is provided. The error handler should reset the stored profile id (if there is one) and re-authenticate, setting forceCreate to true to create a new account. A common cause of this error is deleting the user's account via the Design Portal.
    40207 SWITCHING_PROFILES Indicates that the identity credentials are valid, and the saved profileId is valid, but the identity is not associated with the profileId. This may indicate that the user wants to switch accounts in the app. Often an app will pop-up a dialog confirming that the user wants to switch accounts, and then reset the stored profileId and call authenticate again.
    40208 MISSING_PROFILE_ERROR Returned when the identity cannot be located, no profileId is provided, and forceCreate is false. The normal response is to call Authenticate again with forceCreate set to true.
    40217 UNKNOWN_AUTH_ERROR An unknown error has occurred during authentication.
    40307 TOKEN_DOES_NOT_MATCH_USER The user credentials don't match (i.e. incorrect password).

    GetAlwaysAllowProfileSwitch

    bool allowSwitch = _bc.GetAlwaysAllowProfileSwitch();
    
    
    
    bool alwaysAllow = _bc.AlwaysAllowProfileSwitch;
    
    _bc.AlwaysAllowProfileSwitch = false; // Disables profile switches.
    
    bool allowSwitch = _bc.getAlwaysAllowProfileSwitch();
    
    BOOL allowSwitch = _bc.alwaysAllowProfileSwitch;
    
    var allowSwitch = _bc.getAlwaysAllowProfileSwitch();
    

    For non-anonymous authentication methods, a profile ID will be passed in when this value is set to false. This will generate an error on the server if the profile ID passed in does not match the profile associated with the authentication credentials.

    By default, this value is true.

    GetBC

    //Step 1:   Create and initialize the brainCloud Wrapper 
    //          http://getbraincloud.com/apidocs/apiref/#wrapper
    //Step 2:   Now, you can use Client
    
    BrainCloudClient _bcClient = _bc.Client; // The internal braiCloud client
    
    BrainCloudWrapper->getBC();
    
    BrainCloudClient.Get();
    
    [BrainCloudWrapper getBC];
    
    // N/A
    

    Method returns a singleton instance of the BrainCloudClient.

    GetInstance

    // Enable the Usage of Singleton Mode. Off by Default
    BrainCloudClient.EnableSingletonMode = true;
    
    BrainCloudWrapper.GetInstance();
    
    BrainCloudWrapper bc = BrainCloudWrapper.GetInstance(); // Gets a Singleton instance of brainCloud
    
    BrainCloudWrapper.getInstance();
    
    [BrainCloudWrapper getInstance];
    
    // N/A
    

    Method returns a singleton instance of the BrainCloudWrapper.

    GetStoredAnonymousId

    //Step 1:   Create and initialize the brainCloud Wrapper 
    //          http://getbraincloud.com/apidocs/apiref/#wrapper
    //Step 2:   Now, you can use GetStoredAnonymousId
    
    string anonymousId = _bc.GetStoredAnonymousId();
    
    std::string anonymousId = _bc->getStoredAnonymousId();
    
    String id = _bc.getStoredAnonymousId();
    
    NSString* anonymousId = [_bc getStoredAnonymousId];
    
    var anonymousId = _bc.getStoredAnonymousId();
    

    Returns the stored anonymous ID

    GetStoredProfileId

    //Step 1:   Create and initialize the brainCloud Wrapper 
    //          http://getbraincloud.com/apidocs/apiref/#wrapper
    //Step 2:   Now, you can call GetStoredProfileId
    
    string profileId = _bc.GetStoredProfileId();
    
    std::string profileId = _bc->getStoredProfileId();
    
    String id = _bc.getStoredProfileId();
    
    NSString* profileId = [_bc getStoredProfileId];
    
    var profileId = _bc.getStoredProfileId();
    

    Returns the stored profile ID

    Initialize

    // Unity
    GameObject go = new GameObject();
    _bc = go.AddComponent<BrainCloudWrapper>();
    _bc.WrapperName = _wrapperName; // optionally set a wrapper-name
    _bc.Init(); // extra data, such as: _appId, _secret and _appVersion, is taken from the brainCloud Unity Plugin.
    DontDestroyOnLoad(go); // keep the brainCloud game object through scene changes
    
    // C#
    string serverUrl = "https://sharedprod.braincloudservers.com/dispatcherv2";
    string secret = "1234-1234-1234-1234";
    string appId = "123456";
    string version = "1.0.0";
    
    _bc.Init(serverUrl, secret, appId, version);
    
    
    const char* serverUrl = "https://sharedprod.braincloudservers.com/dispatcherv2";
    const char* secret = "1234-1234-1234-1234";
    const char* appId = "123456";
    const char* version = "1.0.0";
    const char* company = "bitHeads";
    const char* appName = "Awesome Game";
    
    _bc->initialize(serverUrl, secret, appId, version, company, appName);
    
    public void initialize(Context ctx, String appId, String secretKey, String version)
    
    NSString* serverUrl = @"https://sharedprod.braincloudservers.com/dispatcherv2";
    NSString* secret = @"1234-1234-1234-1234";
    NSString* appId = @"123456";
    NSString* appId = @"1.0.0";
    NSString* company = @"bitHeads";
    NSString* appName = @"Awesome Game";
    
    [_bc initialize:serverUrl
          secretKey:secret
              appId:appId
            version:version
         companyName:company
             appName:appName];
    
    secret = "1234-1234-1234-1234";
    appId = "123456";
    
    _bc.initialize(appId, secret, "1.0.0");
    

    Method initializes both BrainCloudWrapper and BrainCloudClient.

    The parameters for this method vary by client (for example the Unity client takes none at all, as all data is pulled from the brainCloud editor menu data).

    Method Parameters
    Parameter Description
    serverURL The URL to the brainCloud server
    secretKey The secret key for your app
    appId The app ID
    version The app version
    companyName Client dependent - The company name used in the keychain for storing anonymous and profile IDs. You are free to pick anything you want.
    appName Client dependent - The app name used in the keychain for storing anonymous and profile IDs. You are free to pick anything you want.

    InitializeWithApps

    // Unity
    GameObject go = new GameObject();
    _bc = go.AddComponent<BrainCloudWrapper>();
    _bc.WrapperName = _wrapperName; // optionally set a wrapper-name
    _bc.InitWithApps(); // extra data, such as: _appId, _secret and _appVersion, is taken from the brainCloud Unity Plugin.
    DontDestroyOnLoad(go); // keep the brainCloud game object through scene changes
    
    // C#
    string serverUrl = "https://sharedprod.braincloudservers.com/dispatcherv2";
    string secret = "86c24079-5299-4659-8159-5352700c3a63";
    string appId = "11787";
    string childSecret = "80704bc0-2903-4f94-bf1d-f4f9fdc2c4f2";
    string childAppId = "11788";
    Dictionary<string, string> secretMap = new Dictionary<string, string>();
    secretMap.Add(appId, secret);
    secretMap.Add(childAppId, childSecret);
    string version = "1.0.0";
    
    _bc = new BrainCloudWrapper();
    _bc.InitWithApps(serverUrl, appId, secretMap, version);
    
    const char* serverUrl = "https://sharedprod.braincloudservers.com/dispatcherv2";
    std::string secret = "86c24079-5299-4659-8159-5352700c3a63";
    std::string appId = "11787";
    std::string childSecret = "80704bc0-2903-4f94-bf1d-f4f9fdc2c4f2";
    std::string childAppId = "11788";
    std::map<std::string, std::string> secretMap;
    secretMap[appId] = secret;
    secretMap[childAppId] = childSecret;
    const char* version = "1.0.0";
    const char* company = "MyCompany Inc.";
    const char* appName = "MyAwesome App";
    
    _bc->initializeWithApps(serverUrl, appId.c_str(), secretMap, version, company, appName);
    
    NSString* serverUrl = @"https://sharedprod.braincloudservers.com/dispatcherv2";
    NSString* secret = @"86c24079-5299-4659-8159-5352700c3a63";
    NSString* appId = @"11787";
    NSString* childSecret = @"80704bc0-2903-4f94-bf1d-f4f9fdc2c4f2";
    NSString* childAppId = @"11788";
    NSDictionary* secretMap = @{
        appId      : secret, 
        childAppId : childSecret,
    };
    NSString* version = @"1.0.0";
    
    [_bc initializeWithApps:serverUrl
                    defaultAppId:appId
                       secretMap:secretMap
                      appVersion:version];
    
    String serverUrl = "https://sharedprod.braincloudservers.com/dispatcherv2";
    String secret = "86c24079-5299-4659-8159-5352700c3a63";
    String appId = "11787";
    String childSecret = "80704bc0-2903-4f94-bf1d-f4f9fdc2c4f2";
    String childAppId = "11788";
    Map<String, String> secretMap = new HashMap<String, String>();
    secretMap.put(appId, secret);
    secretMap.put(childAppId, childSecret);
    String version = "1.0.0";
    
    _bc.initializeWithApps(serverUrl, appId, secretMap, version);
    
    var secret = "86c24079-5299-4659-8159-5352700c3a63";
    var appId = "11787";
    var childSecret = "80704bc0-2903-4f94-bf1d-f4f9fdc2c4f2";
    var childAppId = "11788";
    var secretMap = {};
    secretMap[appId] = secret;
    secretMap[childAppId] = childSecret;
    var version = "1.0.0";
    
    _bc.initializeWithApps(appId, secretMap, version);
    

    Method initializes BrainCloudWrapper and BrainCloudClient with a map of appid->secretkey.

    The parameters for this method vary by client (for example the Unity client takes none at all, as all data is pulled from the brainCloud editor menu data).

    Method Parameters
    Parameter Description
    serverURL The URL to the brainCloud server
    appId The default app ID
    secretMap All app ids to secret keys used by this application
    version The app version
    companyName Client dependent - The company name used in the keychain for storing anonymous and profile IDs. You are free to pick anything you want.
    appName Client dependent - The app name used in the keychain for storing anonymous and profile IDs. You are free to pick anything you want.

    Reconnect

    //Step 1:   Initialize the brainCloud Wrapper and Authenticate the user 
    //          http://getbraincloud.com/apidocs/apiref/#wrapper
    //Step 2:   Now, you can call Reconnect
    
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Success] {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Failed] {0}  {1}  {2}", status, code, error));
    };
    _bc.Reconnect(successCallback, failureCallback);
    
    _bc->reconnect(this);
    
    _bc.reconnect(this);
    
    - (void)reconnect:(BCCompletionBlock)cb
     errorCompletionBlock:(BCErrorCompletionBlock)ecb
            cbObject:(BCCallbackObject)cbObject;
    
    _bc.reconnect(callback);
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": {
            "vcPurchased": 0,
            "experiencePoints": 100,
            "refundCount": 0,
            "playerSessionExpiry": 60,
            "server_time": 1464621990155,
            "experienceLevel": 0,
            "currency": {
                "credits": {
                    "purchased": 0,
                    "balance": 12211,
                    "consumed": 133,
                    "awarded": 12344
                }
            },
            "abTestingId": 8,
            "statistics": {
                "gamesWon": 0
            },
            "id": "323e861-b749-4ce4-a57a-175232e21b5d",
            "createdAt": 1459439058035,
            "profileId": "323e861-b749-4ce4-a57a-175232e21b5d",
            "newUser": "false",
            "xpCapped": false,
            "sent_events": [],
            "timeZoneOffset": -5,
            "playerName": "",
            "vcClaimed": 0,
            "parentProfileId": null,
            "rewards": {
                "rewardDetails": {},
                "rewards": {},
                "currency": {}
            },
            "countryCode": "ca",
            "loginCount": 16,
            "emailAddress": "test@email.com",
            "previousLogin": 1464621979514,
            "incoming_events": [],
            "lastLogin": 1464621990118,
            "languageCode": "en",
            "pictureUrl": null,
            "sessionId": "v3grtg3ve0a089pekk8lneuk8k",
            "amountSpent": 0
        }
    }
    

    Re-authenticates the user with brainCloud

    ResetStoredAnonymousId

    //Step 1:   Create and initialize the brainCloud Wrapper 
    //          http://getbraincloud.com/apidocs/apiref/#wrapper
    //Step 2:   Now, you can call GetAlwaysAllowProfileSwitch
    
    _bc.ResetStoredAnonymousId();
    
    _bc->resetStoredAnonymousId();
    
    _bc.resetStoredAnonymousId();
    
    _bc.storedAnonymousId = @"";
    
    _bc.resetStoredAnonymousId();
    

    Resets the anonymous ID to empty string. When the anonymousId is empty a new one will be generated automatically on authentication.

    ResetStoredProfileId

    //Step 1:   Create and initialize the brainCloud Wrapper 
    //          http://getbraincloud.com/apidocs/apiref/#wrapper
    //Step 2:   Now, you can call GetAlwaysAllowProfileSwitch
    
    _bc.ResetStoredProfileId();
    
    _bc->resetStoredProfileId();
    
    _bc.resetStoredProfileId();
    
    _bc.storedProfileId = @"";
    
    _bc.resetStoredProfileId();
    

    Resets the profile ID to empty string.

    RunCallbacks

    //Step 1:   Create and initialize the brainCloud Wrapper 
    //          http://getbraincloud.com/apidocs/apiref/#wrapper
    //Step 2:   N/A. The brainCloud Wrapper Updates itself using Unity MonoBehavior Update
    //          However, if you are not using Unity or not using the BrainCloudWrapper as a GameObject, call Update in your own update loop
    _bc.Update();
    
    _bc->runCallbacks();
    
    [_bc runCallbacks];
    
    _bc.runCallbacks();
    
    // N/A
    

    Run callbacks, to be called once per frame from your main thread

    SetAlwaysAllowProfileSwitch

    
    
    _bc.SetAlwaysAllowProfileSwitch(false);    // Default is true
    
    _bc->setAlwaysAllowProfileSwitch(true);
    
    _bc.setAlwaysAllowProfileSwitch(true);
    
    _bc.alwaysAllowProfileSwitch = YES;
    
    _bc.setAlwaysAllowProfileSwitch(true);
    

    For non-anonymous authentication methods, a profile ID will be passed in when this value is set to false. This will generate an error on the server if the profile ID passed in does not match the profile associated with the authentication credentials.

    By default, this value is true.

    Method Parameters
    Parameter Description
    alwaysAllow Controls whether the profile ID is passed in with non-anonymous authentications.

    SetStoredAnonymousId

    
    
    _bc.SetStoredAnonymousId("1234-1234-1234-1234");
    
    _bc->setStoredAnonymousId("1234-1234-1234-1234");
    
    // N/A
    
    _bc.storedAnonymousId = @"1234-1234-1234-1234";
    
    _bc.setStoredAnonymousId("1234-1234-1234-1234");
    

    Sets the stored anonymous ID

    Method Parameters
    Parameter Description
    anonymousId The anonymous ID to set

    SetStoredProfileId

    
    
    _bc.SetStoredProfileId("1234-1234-1234-1234");
    
    _bc->setStoredProfileId("1234-1234-1234-1234");
    
    _bc.setStoredProfileId("1234-1234-1234-1234");
    
    _bc.storedProfileId = @"1234-1234-1234-1234";
    
    _bc.setStoredProfileId("1234-1234-1234-1234");
    

    Sets the stored profile ID

    Method Parameters
    Parameter Description
    profileId The profile ID to set

    SmartSwitchAuthentcateEmailPassword

    string email = "my_Email@getbraincloud.com";
    string password = "MyP@ssW0rd!";
    bool forceCreate = true;
    
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Success] {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Failed] {0}  {1}  {2}", status, code, error));
    };
    _bc.SmartSwitchAuthenticateEmailPassword(
        email, password, forceCreate, successCallback, failureCallback);
    
    const char* email = "my_Email@getbraincloud.com";
    const char* password = "MyP@ssW0rd!";
    bool forceCreate = true;
    
    _bc->smartSwitchAuthenticateEmailPassword(email, password, forceCreate, this);
    
    NSString* email = @"my_Email@getbraincloud.com";
    NSString* password = @"MyP@ssW0rd!";
    bool forceCreate = true;
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [_bc smartSwitchAuthenticateEmailPassword:email
                         password:password
                      forceCreate:forceCreate
                  completionBlock:successBlock
             errorCompletionBlock:failureBlock
                         cbObject:nil];
    
    String email = "my_Email@getbraincloud.com";
    String password = "MyP@ssW0rd!";
    boolean forceCreate = true;
    
    _bc.smartSwitchAuthenticateEmailPassword(
        email,
        password,
        forceCreate,
        this);
    
    var email = "my_Email@getbraincloud.com";
    var password = "MyP@ssW0rd!";
    var forceCreate = true;
    
    _bc.smartSwitchAuthenticateEmailPassword(email, password, forceCreate, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    

    Smart Switch Authenticate will logout of the current profile, and switch to the new authentication type. In event the current session was previously an anonymous account, the smart switch will delete that profile. Use this function to keep a clean designflow from anonymous to signed profiles

    Authenticate the user with a custom Email and Password. Note that the client app is responsible for collecting and storing the e-mail and potentially password (for convenience) in the client data. For the greatest security, force the user to re-enter their password at each login (or at least give them that option).

    Method Parameters
    Parameter Description
    email The e-mail address of the user
    password The password of the user
    forceCreate Should a new profile be created for this user if the account does not exist?

    SmartSwitchAuthentcateExternal

    string userId = "externalId";
    string token = "externalTokenOrPassword";
    string externalAuthName = "nameOfExternalAuthService";
    bool forceCreate = true;
    
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Success] {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Failed] {0}  {1}  {2}", status, code, error));
    };
    _bc.SmartSwitchAuthenticateExternal(
        userId, token, externalAuthName, forceCreate,
        successCallback, failureCallback);
    
    const char* userId = "externalId";
    const char* token = "externalTokenOrPassword";
    const char* externalAuthName = "nameOfExternalAuthService";
    
    _bc->smartSwitchAuthenticateExternal(
        userId,
        token,
        externalAuthName,
        true,
        this);
    
    NSString* authId = @"1234";
    NSString* authToken = @"1234-1234-1234-1234";
    NSString* externalAuthName = @"externalSystem";
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [_bc smartSwitchAuthenticateExternal:authId
             authenticationToken:authToken
      externalAuthenticationName:externalAuthName
                     forceCreate:true
                 completionBlock:successBlock
            errorCompletionBlock:failureBlock
                        cbObject:nil];
    
    String userId = "externalId";
    String token = "externalTokenOrPassword";
    String externalAuthName = "nameOfExternalAuthService";
    
    _bc.smartSwitchAuthenticateExternal(
        userId,
        token,
        externalAuthName,
        true,
        this);
    
    var userId = "externalId";
    var token = "externalTokenOrPassword";
    var externalAuthName = "nameOfExternalAuthService";
    var forceCreate = true;
    
    _bc.smartSwitchAuthenticateExternal(userId, token, externalAuthName, forceCreate, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    

    Smart Switch Authenticate will logout of the current profile, and switch to the new authentication type. In event the current session was previously an anonymous account, the smart switch will delete that profile. Use this function to keep a clean designflow from anonymous to signed profiles

    Authenticate the user via cloud code (which in turn validates the supplied credentials against an external system). This allows the developer to extend brainCloud authentication to support other backend authentication systems.

    Method Parameters
    Parameter Description
    userId The userId
    token The user token (password etc)
    externalAuthName The name of the custom authentication type (linked to a cloud script that performs authentication). Configured via the Design | Authentication | External page of the Design Portal.
    forceCreate Should a new profile be created for this user if the account does not exist?

    SmartSwitchAuthentcateFacebook

    string facebookId = "userFacebookId";
    string token = "tokenFromFacebook";
    bool forceCreate = true;
    
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Success] {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Failed] {0}  {1}  {2}", status, code, error));
    };
    _bc.SmartSwitchAuthenticateFacebook(
        facebookId, token, forceCreate,
        successCallback, failureCallback);
    
    const char* facebookId = "userFacebookId";
    const char* token = "tokenFromFacebook";
    
    _bc->smartSwitchAuthenticateFacebook(
        userId,
        token,
        true,
        this);
    
    NSString* externalID = @"userFacebookId";
    NSString* authToken = @"tokenFromFacebook";
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [_bc smartSwitchAuthenticateExternal:externalID
             authenticationToken:authToken
                     forceCreate:true
                 completionBlock:successBlock
            errorCompletionBlock:failureBlock
                        cbObject:nil];
    
    public void smartSwitchAuthenticateFacebook(String fbUserId, String fbAuthToken, boolean forceCreate, IAuthenticationServiceCallback callback)
    
    var facebookId = "userFacebookId";
    var token = "tokenFromFacebook";
    var forceCreate = true;
    
    _bc.smartSwitchAuthenticateFacebook(facebookId, token, forceCreate, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    

    Smart Switch Authenticate will logout of the current profile, and switch to the new authentication type. In event the current session was previously an anonymous account, the smart switch will delete that profile. Use this function to keep a clean designflow from anonymous to signed profiles

    Authenticate the user with brainCloud using their Facebook Credentials

    Method Parameters
    Parameter Description
    userId The userId
    facebookId The Facebook ID of the user
    facebookToken The validated token from the Facebook SDK
    forceCreate Should a new profile be created for this user if the account does not exist?

    SmartSwitchAuthentcateGameCenter

    string gameCenterId = "userGameCenterId";
    bool forceCreate = true;
    
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Success] {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Failed] {0}  {1}  {2}", status, code, error));
    };
    _bc.SmartSwitchAuthenticateGameCenter(
        gameCenterId, forceCreate,
        successCallback, failureCallback);
    
    const char* gameCenterId = "userGameCenterId";
    
    _bc->smartSwitchAuthenticateGameCenter(
        gameCenterId,
        true,
        this);
    
    NSString* gameCenterID = @"userGameCenterId";
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [_bc smartSwitchAuthenticateGameCenter:gameCenterID
                     forceCreate:true
                 completionBlock:successBlock
            errorCompletionBlock:failureBlock
                        cbObject:nil];
    
    // N/A
    
    var gameCenterId = "userGameCenterId";
    var forceCreate = true;
    
    _bc.smartSwitchAuthenticateGameCenter(gameCenterId, forceCreate, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    

    Smart Switch Authenticate will logout of the current profile, and switch to the new authentication type. In event the current session was previously an anonymous account, the smart switch will delete that profile. Use this function to keep a clean designflow from anonymous to signed profiles

    Authenticate the user using their Game Center id

    Method Parameters
    Parameter Description
    gameCenterId The player's game center ID (use the playerID property from the local GKPlayer object)
    forceCreate Should a new profile be created for this user if the account does not exist?

    SmartSwitchAuthentcateGoogle

    string googleId = "myUser@gmail.com";
    string token = "authTokenFromGoogle";
    bool forceCreate = true;
    
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Success] {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Failed] {0}  {1}  {2}", status, code, error));
    };
    _bc.SmartSwitchAuthenticateGoogle(
        googleId, token, forceCreate,
        successCallback, failureCallback);
    
    const char* googleId = "myUser@gmail.com";
    const char* token = "authTokenFromGoogle";
    
    _bc->smartSwitchAuthenticateGoogle(
        googleId, token, true, this);
    
    NSString* userID = @"myUser@gmail.com";
    NSString* token = @"authTokenFromGoogle";
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [_bc smartSwitchAuthenticateGoogle:userID
                          token:token
                    forceCreate:true
                completionBlock:successBlock
           errorCompletionBlock:failureBlock
                       cbObject:nil];
    
    String googleId = "myUser@gmail.com";
    String token = "authTokenFromGoogle";
    
    _bc.smartSwitchAuthenticateGoogle(
        googleId, token, true, this);
    
    var googleId = "myUser@gmail.com";
    var token = "authTokenFromGoogle";
    var forceCreate = true;
    
    _bc.smartSwitchAuthenticateGoogle(googleId, token, forceCreate, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    

    Smart Switch Authenticate will logout of the current profile, and switch to the new authentication type. In event the current session was previously an anonymous account, the smart switch will delete that profile. Use this function to keep a clean designflow from anonymous to signed profiles

    Authenticate the user using a google user id (email address) and google authentication token.

    Method Parameters
    Parameter Description
    googleId String representation of google+ userid (email)
    googleToken The authentication token derived via the google apis.
    forceCreate Should a new profile be created for this user if the account does not exist?

    SmartSwitchAuthentcateSteam

    string steamId = "userSteamId";
    string ticket = "sessionTicketFromSteam";
    bool forceCreate = true;
    
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Success] {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Failed] {0}  {1}  {2}", status, code, error));
    };
    _bc.SmartSwitchAuthenticateSteam(
        steamId, ticket, forceCreate,
        successCallback, failureCallback);
    
    const char* steamId = "userSteamId";
    const char* ticket = "sessionTicketFromSteam";
    
    _bc->smartSwitchAuthenticateSteam(
        steamId, token, true, this);
    
    NSString* userID = @"userSteamId";
    NSString* sessionticket = @"sessionTicketFromSteam";
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [_bc smartSwitchAuthenticateSteam:userID
                 sessionTicket:sessionticket
                   forceCreate:true
               completionBlock:successBlock
          errorCompletionBlock:failureBlock
                      cbObject:nil];
    
    Steam steamId = "userSteamId";
    Steam ticket = "sessionTicketFromSteam";
    
    _bc.smartSwitchAuthenticateSteam(
        steamId, token, true, this);
    
    var steamId = "userSteamId";
    var ticket = "sessionTicketFromSteam";
    var forceCreate = true;
    
    _bc.smartSwitchAuthenticateSteam(steamId, ticket, forceCreate, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    

    Smart Switch Authenticate will logout of the current profile, and switch to the new authentication type. In event the current session was previously an anonymous account, the smart switch will delete that profile. Use this function to keep a clean designflow from anonymous to signed profiles

    Authenticate the user using a steam userId and session ticket (without any validation on the userId).

    Method Parameters
    Parameter Description
    userId String representation of 64 bit steam ID
    sessionTicket The session ticket of the user (hex encoded)
    forceCreate Should a new profile be created for this user if the account does not exist?

    SmartSwitchAuthentcateTwitter

    string twitterId = "userTwitterId";
    string token = "userAuthToken";
    string secret = "secretFromTwitterApi";
    bool forceCreate = true;
    
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Success] {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Failed] {0}  {1}  {2}", status, code, error));
    };
    _bc.SmartSwitchAuthenticateTwitter(
        twitterId, token, secret, forceCreate,
        successCallback, failureCallback);
    
    const char* twitterId = "userTwitterId";
    const char* token = "userAuthToken";
    const char* secret = "secretFromTwitterApi";
    
    _bc->smartSwitchAuthenticateTwitter(
        twitterId, token, secret, true, this);
    
    NSString* twitterId = @"userTwitterId";
    NSString* token = @"userAuthToken";
    NSString* secret = @"secretFromTwitterApi";
    BOOL forceCreate = true;
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
        [_bc smartSwitchAuthenticateTwitter:userID
                          token:token
                         secret:secret
                    forceCreate:forceCreate
                completionBlock:successBlock
           errorCompletionBlock:failureBlock
                       cbObject:nil];
    
    String twitterId = "userTwitterId";
    String token = "userAuthToken";
    String secret = "secretFromTwitterApi";
    
    _bc.smartSwitchAuthenticateTwitter(
        twitterId, token, secret, true, this);
    
    var twitterId = "userTwitterId";
    var token = "userAuthToken";
    var secret = "secretFromTwitterApi";
    var forceCreate = true;
    
    _bc.smartSwitchAuthenticateTwitter(twitterId, token, secret, forceCreate, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    

    Smart Switch Authenticate will logout of the current profile, and switch to the new authentication type. In event the current session was previously an anonymous account, the smart switch will delete that profile. Use this function to keep a clean designflow from anonymous to signed profiles

    Authenticate the user using a Twitter user ID, authentication token, and secret from Twitter

    Method Parameters
    Parameter Description
    userId String representation of Twitter user ID
    token The authentication token derived via the Twitter APIs
    secret The secret given when attempting to link with Twitter
    forceCreate Should a new profile be created for this user if the account does not exist?

    SmartSwitchAuthentcateUniversal

    const char* userId = "MyUserName_007";
    const char* password = "MyP@ssW0rd!";
    bool forceCreate = true;
    
    _bc->smartSwitchAuthenticateUniversal(userId, password, forceCreate, this);
    
    string userId = "MyUserName_007";
    string password = "MyP@ssW0rd!";
    bool forceCreate = true;
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Success] {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Failed] {0}  {1}  {2}", status, code, error));
    };
    
    _bc.SmartSwitchAuthenticateUniversal(userId, password, forceCreate, successCallback, failureCallback);
    
    String userId = "MyUserName_007";
    String password = "MyP@ssW0rd!";
    boolean forceCreate = true;
    
    _bc.smartSwitchAuthenticateUniversal(userId, password, forceCreate, this);
    
    NSString* userId = @"MyUserName_007";
    NSString* password = @"MyP@ssW0rd!";
    bool forceCreate = true;
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [_bc smartSwitchAuthenticateUniversal:userId
                   password:password
                forceCreate:forCreate
            completionBlock:successBlock
       errorCompletionBlock:failureBlock
                   cbObject:nil];
    
    var userId = "MyUserName_007";
    var password = "MyP@ssW0rd!";
    var forceCreate = true;
    
    _bc.smartSwitchAuthenticateUniversal(userId, password, forceCreate, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    

    Smart Switch Authenticate will logout of the current profile, and switch to the new authentication type. In event the current session was previously an anonymous account, the smart switch will delete that profile. Use this function to keep a clean designflow from anonymous to signed profiles

    Method authenticates the user using universal credentials

    Method Parameters
    Parameter Description
    userId The user's ID.
    password The password of the user.
    forceCreate Should a new profile be created for this user if the account does not exist?

    Client API

    Authentication

    This section describes the key methods for implementing basic authentication in your app. These methods are all you'll need if you:

    Consult the advanced (Identity) section if/when you want to get even more flexible with authentication (giving users more flexibility to choose their preferred authentication method, merging of profiles, etc.) When implementing brainCloud authentication, there are some key things to keep in mind:

    brainCloud uses an anonymous installation ID (commonly referred to as the anonymous ID) to identify individual devices. This ID must be generated for first use, and saved by the client application. brainCloud provides a convenient method for generating the ID – or the developer can generate it themselves. brainCloud also requires the client to keep track of the most recent profile ID. This, together with the anonymous ID, provides additional security and allows brainCloud to better understand user intent during logins/reconnections. If the user has never connected before the profile ID should be null.

    If you are using the API Explorer, the list of valid Platform IDs can be found here.

    Handy tip: To log a user out of brainCloud, use the Logout method in PlayerState. Note that you don't absolutely need to log users out – their sessions will timeout on the server automatically anyway.

    By default, the timeout length for authenticated users is 20 minutes. This timeout length can be lowered on the brainCloud Dashboard. [Core App Info | Advance Settings > Session Timeout]

    Version Enforcement

    brainCloud's authentication mechanisms allow you to enforce minimum client version requirements – forcing users with obsolete versions of your client app to upgrade before continuing within your application. This is especially useful for scenarios where you've fixed critical client errors, made significant changes to the server-side data structures, or generally just want to ensure that your users all have the best possible experience.

    The client app version (sometimes referred to as the gameVersion) is sent to the server during authentication. It is a string of format "X.X" or "X.X.X" – for example, "1.0.0". The app version is set via the Client or BrainCloudWrapper Initialize() methods.

    The minimum versions that your app supports can be configured on the Core App Info | Platforms page of the design portal.

    If the client app is older than the minimum version specified, authenticate will return a result similar to:

    { "status": 400, "reason_code": 40322, "upgradeAppId": "http://itunes.com/apps/myappname", "status_message": "Processing exception (message): Game version 1.0.0 is obsolete." }

    Recommended behavior of the client is to pop up a dialog inviting the user to upgrade the client, and then redirect them to the appropriate software update page. Note that an upgrade URL may be data-filled with the minimum version # in the server portal.

    Disabled Apps

    brainCloud allows you to easily control whether your app is enabled or disabled via the Core App Info | Advanced Settings page of the portal.

    If for some reason you do decide to disable your app, you are able to configure a custom JSON object to be returned to apps that attempt to login. This JSON is set via the [Edit Disabled Reason] button on that same portal page.

    Once disabled, your provided JSON-data will be returned within an element called disabledReason within the error response. For example: { "reason_code": 40330, "status": 403, "status_message": "Processing exception (bundle): Game is disabled.", "disabledReason": { "message": "Apologies - we will be right back!" }, "severity": "ERROR" }

    System Disabled

    If for some reason your app is System Disabled by brainCloud operations, your app will receive a disabledReason with two elements: sysDisabled: true and message.

    { "reason_code": 40330, "status": 403, "status_message": "Processing exception (bundle): Game is disabled.", "disabledReason": { "sysDisabled": true, "message": "This app has been system disabled. Please contact support." }, "severity": "ERROR" }

    API Summary

    Initialization
    Authentication
    Utility

    AuthenticateAnonymous

    // if it's a new user
    const char* newAnonId = _bc->generateGUID();
    _bc->initializeIdentity(NULL, newAnonId);
    _bc->getAuthenticationService()->authenticateAnonymous(true, this);
    
    // if it's an existing user
    const char* savedProfileId = yourMethodToGetSavedProfileId();
    const char* savedAnonId = yourMethodToGetSavedAnonymousId();
    _bc->initializeIdentity(savedProfileId, savedAnonId);
    _bc->getAuthenticationService()->authenticateAnonymous(false, this);
    
    // note you can also use the BrainCloudWrapper class
    
    bool forceCreate = true;
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("Success | {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("Failed | {0}  {1}  {2}", status, code, error));
    };
    
    _bc.AuthenticationService.AuthenticateAnonymous(forceCreate, successCallback, failureCallback);
    
    BOOL forceCreate = true;
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [[_bc authenticationService] authenticateAnonymous:forceCreate
                completionBlock:successBlock
           errorCompletionBlock:failureBlock
                       cbObject:nil];
    
    boolean includeOffline = true;
    this; // implements IServerCallback
    
    _bc.GetAuthenticationService().AuthenticateAnonymous(includeOffline, this);
    
    public void serverCallback(ServiceName serviceName, ServiceOperation serviceOperation, JSONObject jsonData)
    {
        System.out.print(String.format("Success | %s", jsonData.toString()));
    }
    public void serverError(ServiceName serviceName, ServiceOperation serviceOperation, int statusCode, int reasonCode, String jsonError)
    {
        System.out.print(String.format("Failed | %d %d %s", statusCode,  reasonCode, jsonError.toString()));
    }
    
    var forceCreate = true;
    
    _bc.authentication.authenticateAnonymous(forceCreate, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    // N/A
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": {
            "vcPurchased": 0,
            "experiencePoints": 100,
            "refundCount": 0,
            "playerSessionExpiry": 60,
            "server_time": 1464621990155,
            "experienceLevel": 0,
            "currency": {
                "credits": {
                    "purchased": 0,
                    "balance": 12211,
                    "consumed": 133,
                    "awarded": 12344
                }
            },
            "abTestingId": 8,
            "statistics": {
                "gamesWon": 0
            },
            "id": "323e861-b749-4ce4-a57a-175232e21b5d",
            "createdAt": 1459439058035,
            "profileId": "323e861-b749-4ce4-a57a-175232e21b5d",
            "newUser": "false",
            "xpCapped": false,
            "sent_events": [],
            "timeZoneOffset": -5,
            "playerName": "",
            "vcClaimed": 0,
            "parentProfileId": null,
            "rewards": {
                "rewardDetails": {},
                "rewards": {},
                "currency": {}
            },
            "countryCode": "ca",
            "loginCount": 16,
            "emailAddress": "test@email.com",
            "previousLogin": 1464621979514,
            "incoming_events": [],
            "lastLogin": 1464621990118,
            "languageCode": "en",
            "pictureUrl": null,
            "sessionId": "v3grtg3ve0a089pekk8lneuk8k",
            "amountSpent": 0
        }
    }
    

    To authenticate anonymously you must have first called InitializeIdentity. You must supply an anonymous ID if you are creating a brand new profile or if you are logging into an already created profile you need to supply the anonymous ID AND the profile ID of the user.

    Once you've logged in successfully make sure to save the anonymous and profile ID for future logins.

    You can generate a new anonymous ID using the convenience method GenerateAnonymousId.

    Service Operation
    "authenticationV2" "AUTHENTICATE"
    Method Parameters
    Parameter Description
    forceCreate If set to true, create a new profile if anonymous ID not found. If set to false and anonymous ID does not exist on the server, return an error.
    Show Example Error Handling {}
    public void FailureCallback(int statusCode, int reasonCode, string statusMessage, object cbObject) {
        switch (reasonCode) {
            case ReasonCodes.MISSING_IDENTITY_ERROR: { // Anonymous id is invalid
    
                // Clear the profile id, generate a new Anonymous id, and re-authenticate
                BrainCloudClient.Get().AuthenticationService.ClearSavedProfileID();
                BrainCloudClient.Get().AuthenticationService.AnonymousId =
                    BrainCloudClient.Get().AuthenticationService.GenerateAnonymousId();
                BrainCloudClient.Get().AuthenticationService.AuthenticateAnonymous(true, OnSuccess_Authenticate, OnError_AuthenticateAnonymous);
                break;
            }
            case ReasonCodes.MISSING_PROFILE_ERROR: { // Anonymous id doesn't exist in database
    
                // The account doesn't exist - create it now.
                BrainCloudClient.Get().AuthenticationService.AuthenticateAnonymous(true, OnSuccess_Authenticate, OnError_AuthenticateAnonymous);
                break;
            }
            case ReasonCodes.SWITCHING_PROFILES: {  // Identity belongs to a different profile
    
                // Clear the profile id, generate a new Anonymous id, and re-authenticate
                BrainCloudClient.Get().AuthenticationService.ClearSavedProfileID();
                BrainCloudClient.Get().AuthenticationService.AnonymousId =
                    BrainCloudClient.Get().AuthenticationService.GenerateAnonymousId();
                BrainCloudClient.Get().AuthenticationService.AuthenticateAnonymous(true, OnSuccess_Authenticate, OnError_AuthenticateAnonymous);
                break;
            }
            case ReasonCodes.SECURITY_ERROR: { // Identity is invalid
                // Generate a new Anonymous id, and re-authenticate
                BrainCloudClient.Get().AuthenticationService.AnonymousId =
                    BrainCloudClient.Get().AuthenticationService.GenerateAnonymousId();
                BrainCloudClient.Get().AuthenticationService.AuthenticateAnonymous(true, OnSuccess_Authenticate, OnError_AuthenticateAnonymous);
                break;
            }
            case ReasonCodes.MISSING_REQUIRED_PARAMETER: { // Anonymous id cannot be blank
                // Generate an Anonymous id before calling AuthenticateAnonymous
                BrainCloudClient.Get().AuthenticationService.AnonymousId =
                    BrainCloudClient.Get().AuthenticationService.GenerateAnonymousId();
                BrainCloudClient.Get().AuthenticationService.AuthenticateAnonymous(true, OnSuccess_Authenticate, OnError_AuthenticateAnonymous);
                break;
            }
            default: { // Uncaught reasonCode
                /**
                 * Log the unexpected reasonCode to your own internal logs,
                 * to implement needed error handling later
                 */
                break;
            }
        }
    }
    
    Error returns
    Code Name Description
    40206 MISSING_IDENTITY_ERROR Both an anonymousId and profileId were provided for authentication - but the anonymousId doesn't exist on the server. The profileId may or may not exist. It is possible that the user account was deleted via the Design Portal. The proper recourse is to reset the stored profile id, and re-authenticate. [There is no need to delete the anonymousId since it doesn't exist on the server anyway.]
    40207 SWITCHING_PROFILES This means that the anonymousId provided does point to a profile, but not the same one that was saved in the client. This fails the anonymous security check. For any other authentication type, this might indicate that the user wants to switch accounts (thus the name of the error constant). For anonymous, the only response is to reset both the stored anonymousId and profileId, and then re-authenticate.
    40208 MISSING_PROFILE_ERROR The anonymousId provided is not associated with an existing profile and forceCreate = false. To create an account, retry with forceCreate = true.
    40209 SECURITY_ERROR Occurs when attempting to authenticate anonymously to an existing user without providing the matching profile ID
    40217 UNKNOWN_AUTH_ERROR An unknown error has occurred on authentication
    40358 MISSING_REQUIRED_PARAMETER The provided anonymous ID cannot be null

    AuthenticateEmailPassword

    string email = "someEmail@somedomain.com";
    string password = "userPassword";
    bool forceCreate = true;
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("Success | {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("Failed | {0}  {1}  {2}", status, code, error));
    };
    
    _bc.AuthenticationService.AuthenticateEmailPassword(
        email, password, forceCreate, successCallback, failureCallback);
    
    const char* email = "someEmail@somedomain.com";
    const char* password = "userPassword";
    bool forceCreate = true;
    
    _bc->getAuthenticationService()->authenticateEmailPassword(
        email,
        password,
        forceCreate,
        this);
    
    NSString * email = @"someEmail@somedomain.com";
    NSString * password = @"userPassword";
    BOOL forceCreate = true;
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [[_bc authenticationService]
            authenticateEmailPassword:email
                     password:password
                  forceCreate:forceCreate
              completionBlock:successBlock
         errorCompletionBlock:failureBlock
                     cbObject:nil];
    
    String email = "someEmail@somedomain.com";
    String password = "userPassword";
    boolean forceCreate = true;
    this; // implements IServerCallback
    
    _bc.getAuthenticationService().authenticateEmailPassword(email, password, forceCreate, this);
    
    public void serverCallback(ServiceName serviceName, ServiceOperation serviceOperation, JSONObject jsonData)
    {
        System.out.print(String.format("Success | %s", jsonData.toString()));
    }
    public void serverError(ServiceName serviceName, ServiceOperation serviceOperation, int statusCode, int reasonCode, String jsonError)
    {
        System.out.print(String.format("Failed | %d %d %s", statusCode,  reasonCode, jsonError.toString()));
    }
    
    var email = "someEmail@somedomain.com";
    var password = "userPassword";
    var forceCreate = true;
    
    _bc.authentication.authenticateEmailPassword(email, password, forceCreate, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    // N/A
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": {
            "vcPurchased": 0,
            "experiencePoints": 100,
            "refundCount": 0,
            "playerSessionExpiry": 60,
            "server_time": 1464621990155,
            "experienceLevel": 0,
            "currency": {
                "credits": {
                    "purchased": 0,
                    "balance": 12211,
                    "consumed": 133,
                    "awarded": 12344
                }
            },
            "abTestingId": 8,
            "statistics": {
                "gamesWon": 0
            },
            "id": "323e861-b749-4ce4-a57a-175232e21b5d",
            "createdAt": 1459439058035,
            "profileId": "323e861-b749-4ce4-a57a-175232e21b5d",
            "newUser": "false",
            "xpCapped": false,
            "sent_events": [],
            "timeZoneOffset": -5,
            "playerName": "",
            "vcClaimed": 0,
            "parentProfileId": null,
            "rewards": {
                "rewardDetails": {},
                "rewards": {},
                "currency": {}
            },
            "countryCode": "ca",
            "loginCount": 16,
            "emailAddress": "test@email.com",
            "previousLogin": 1464621979514,
            "incoming_events": [],
            "lastLogin": 1464621990118,
            "languageCode": "en",
            "pictureUrl": null,
            "sessionId": "v3grtg3ve0a089pekk8lneuk8k",
            "amountSpent": 0
        }
    }
    

    Authenticate the user with a custom Email and Password. Note that the client app is responsible for collecting (and storing) the e-mail and potentially password (for convenience) in the client data. For the greatest security, force the user to re-enter their password at each login (or at least give them that option).

    Service Operation
    "authenticationV2" "AUTHENTICATE"
    Method Parameters
    Parameter Description
    email The e-mail address of the user
    password The password of the user
    forceCreate Should a new profile be created for this user if the account does not exist?
    Show Example Error Handling {}
    public void FailureCallback(int statusCode, int reasonCode, string statusMessage, object cbObject) {
        switch (reasonCode) {
            case ReasonCodes.MISSING_IDENTITY_ERROR: { // Identity does not exist (and client has orphaned profileId)
    
                // Reset profileId and re-authenticate
                BrainCloudClient.Get().AuthenticationService.ResetStoredProfileId();
                BrainCloudClient.Get().AuthenticationService.AuthenticateEmail(email, password, true);
                break;
            }
            case ReasonCodes.SWITCHING_PROFILES: { // Identity belongs to a different profile
    
                // Reset profileId and re-authenticate
                BrainCloudClient.Get().AuthenticationService.ResetStoredProfileId();
                BrainCloudClient.Get().AuthenticationService.AuthenticateEmail(email, password, forceCreate);
                break;
            }
            case ReasonCodes.MISSING_PROFILE_ERROR: { // Identity does not exist
    
                // The account doesn't exist - create it now.
                BrainCloudClient.Get().AuthenticationService.AuthenticateEmail(email, password, true);
                break;
            }
            case ReasonCodes.TOKEN_DOES_NOT_MATCH_USER: { // User auth information is incorrect
    
                // Display a dialog telling the user that the password provided was invalid,
                // and invite them to re-enter the password.
                // ...
                break;
            }
            default: { // Uncaught reasonCode
    
                // Log the error for debugging later
                // ...
                break;
            }
        }
    }
    
    Error returns
    Code Name Description
    40206 MISSING_IDENTITY_ERROR The identity does not exist on the server and forceCreate was false [and a profileId was provided - otherwise 40208 would have been returned]. Will also occur when forceCreate is true and a saved [but un-associated] profileId is provided. The error handler should reset the stored profile id (if there is one) and re-authenticate, setting forceCreate to true to create a new account. A common cause of this error is deleting the user's account via the Design Portal.
    40207 SWITCHING_PROFILES Indicates that the identity credentials are valid, and the saved profileId is valid, but the identity is not associated with the provided profileId. This may indicate that the user wants to switch accounts in the app. Most often an app will pop-up a dialog confirming that the user wants to switch accounts, and then reset the stored profileId and call authenticate again.
    40208 MISSING_PROFILE_ERROR Returned when the identity cannot be located, no profileId is provided, and forceCreate is false. The normal response is to call Authenticate again with forceCreate set to true.
    40217 UNKNOWN_AUTH_ERROR An unknown error has occurred during authentication.
    40307 TOKEN_DOES_NOT_MATCH_USER The user's password is incorrect.

    AuthenticateExternal

    string userId = "externalId";
    string token = "externalTokenOrPassword";
    string externalAuthName = "nameOfExternalAuthService";
    bool includeOffline = true;
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("Success | {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("Failed | {0}  {1}  {2}", status, code, error));
    };
    
    _bc.AuthenticationService.AuthenticateExternal(
        userId, token, externalAuthName, forceCreate,
        successCallback, failureCallback);
    
    const char* userId = "externalId";
    const char* token = "externalTokenOrPassword";
    const char* externalAuthName = "nameOfExternalAuthService";
    bool forceCreate = true;
    
    _bc->getAuthenticationService()->authenticateExternal(
        userId,
        token,
        externalAuthName,
        forceCreate,
        this);
    
    NSString * userID = @"externalId";
    NSString * token = @"externalTokenOrPassword";
    NSString * externalAuthName = @"nameOfExternalAuthService";
    BOOL forceCreate = true;
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [[_bc authenticationService]
                authenticateExternal:userID
                 authenticationToken:authToken
          externalAuthenticationName:externalAuthName
                         forceCreate:forceCreate
                     completionBlock:successBlock
                errorCompletionBlock:failureBlock
                            cbObject:nil];
    
    String userID = "externalId";
    String token = "externalTokenOrPassword";
    String externalAuthName = "nameOfExternalAuthService";
    boolean forceCreate = true;
    this; // implements IServerCallback
    
    _bc.getAuthenticationService().authenticateExternal(userID, token, externalAuthName, forceCreate, this);
    
    public void serverCallback(ServiceName serviceName, ServiceOperation serviceOperation, JSONObject jsonData)
    {
        System.out.print(String.format("Success | %s", jsonData.toString()));
    }
    public void serverError(ServiceName serviceName, ServiceOperation serviceOperation, int statusCode, int reasonCode, String jsonError)
    {
        System.out.print(String.format("Failed | %d %d %s", statusCode,  reasonCode, jsonError.toString()));
    }
    
    var userID = "externalId";
    var token = "externalTokenOrPassword";
    var externalAuthName = "nameOfExternalAuthService";
    var forceCreate = true;
    
    _bc.authentication.authenticateExternal(userID, token, externalAuthName, forceCreate, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    // N/A
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": {
            "vcPurchased": 0,
            "experiencePoints": 100,
            "refundCount": 0,
            "playerSessionExpiry": 60,
            "server_time": 1464621990155,
            "experienceLevel": 0,
            "currency": {
                "credits": {
                    "purchased": 0,
                    "balance": 12211,
                    "consumed": 133,
                    "awarded": 12344
                }
            },
            "abTestingId": 8,
            "statistics": {
                "gamesWon": 0
            },
            "id": "323e861-b749-4ce4-a57a-175232e21b5d",
            "createdAt": 1459439058035,
            "profileId": "323e861-b749-4ce4-a57a-175232e21b5d",
            "newUser": "false",
            "xpCapped": false,
            "sent_events": [],
            "timeZoneOffset": -5,
            "playerName": "",
            "vcClaimed": 0,
            "parentProfileId": null,
            "rewards": {
                "rewardDetails": {},
                "rewards": {},
                "currency": {}
            },
            "countryCode": "ca",
            "loginCount": 16,
            "emailAddress": "test@email.com",
            "previousLogin": 1464621979514,
            "incoming_events": [],
            "lastLogin": 1464621990118,
            "languageCode": "en",
            "pictureUrl": null,
            "sessionId": "v3grtg3ve0a089pekk8lneuk8k",
            "amountSpent": 0
        }
    }
    

    Authenticate the user via cloud code (which in turn validates the supplied credentials against an external system). This allows the developer to extend brainCloud authentication to support other backend authentication systems.

    Service Operation
    "authenticationV2" "AUTHENTICATE"
    Method Parameters
    Parameter Description
    userId The userId
    token The user token (password etc)
    externalAuthName The name of the cloud script to call for external authentication
    forceCreate Should a new profile be created for this user if the account does not exist?
    Error returns
    Code Name Description
    40206 MISSING_IDENTITY_ERROR The identity does not exist on the server and forceCreate was false [and a profileId was provided - otherwise 40208 would have been returned]. Will also occur when forceCreate is true and a saved [but un-associated] profileId is provided. The error handler should reset the stored profile id (if there is one) and re-authenticate, setting forceCreate to true to create a new account. A common cause of this error is deleting the user's account via the Design Portal.
    40207 SWITCHING_PROFILES Indicates that the identity credentials are valid, and the saved profileId is valid, but the identity is not associated with the provided profileId. This may indicate that the user wants to switch accounts in the app. Often an app will pop-up a dialog confirming that the user wants to switch accounts, and then reset the stored profileId and call authenticate again.
    40208 MISSING_PROFILE_ERROR Returned when the identity cannot be located, no profileId is provided, and forceCreate is false. The normal response is to call Authenticate again with forceCreate set to true.
    40217 UNKNOWN_AUTH_ERROR An unknown error has occurred during authentication.
    40307 TOKEN_DOES_NOT_MATCH_USER The user credentials don't match (according to the 3rd party system). May also indicate an issue with the external authentication script.

    AuthenticateFacebook

    string facebookId = "userFacebookId";
    string token = "tokenFromFacebook";
    bool forceCreate = true;
    
    _bc.AuthenticationService.AuthenticateFacebook(
        facebookId, token, forceCreate, SuccessCallback, FailureCallback);
    
    const char* facebookId = "userFacebookId";
    const char* token = "tokenFromFacebook";
    bool forceCreate = true;
    
    _bc->getAuthenticationService()->authenticateFacebook(
        facebookId,
        token,
        forceCreate,
        this);
    
    NSString * facebookId = @"userFacebookId";
    NSString * token = @"tokenFromFacebook";
    BOOL forceCreate = true;
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [[_bc authenticationService]
               authenticateFacebook:facebookId
                authenticationToken:token
                        forceCreate:forceCreate
                    completionBlock:successBlock
               errorCompletionBlock:failureBlock
                           cbObject:nil];
    
    String facebookId = "userFacebookId";
    String token = "tokenFromFacebook";
    boolean forceCreate = true;
    this; // implements IServerCallback
    
    _bc.getAuthenticationService().authenticateFacebook(facebookId, token, forceCreate, this);
    
    public void serverCallback(ServiceName serviceName, ServiceOperation serviceOperation, JSONObject jsonData)
    {
        System.out.print(String.format("Success | %s", jsonData.toString()));
    }
    public void serverError(ServiceName serviceName, ServiceOperation serviceOperation, int statusCode, int reasonCode, String jsonError)
    {
        System.out.print(String.format("Failed | %d %d %s", statusCode,  reasonCode, jsonError.toString()));
    }
    
    var facebookId = "userFacebookId";
    var token = "tokenFromFacebook";
    var forceCreate = true;
    
    _bc.authentication.authenticateFacebook(facebookId, token, forceCreate, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    // N/A
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": {
            "vcPurchased": 0,
            "experiencePoints": 100,
            "refundCount": 0,
            "playerSessionExpiry": 60,
            "server_time": 1464621990155,
            "experienceLevel": 0,
            "currency": {
                "credits": {
                    "purchased": 0,
                    "balance": 12211,
                    "consumed": 133,
                    "awarded": 12344
                }
            },
            "abTestingId": 8,
            "statistics": {
                "gamesWon": 0
            },
            "id": "323e861-b749-4ce4-a57a-175232e21b5d",
            "createdAt": 1459439058035,
            "profileId": "323e861-b749-4ce4-a57a-175232e21b5d",
            "newUser": "false",
            "xpCapped": false,
            "sent_events": [],
            "timeZoneOffset": -5,
            "playerName": "",
            "vcClaimed": 0,
            "parentProfileId": null,
            "rewards": {
                "rewardDetails": {},
                "rewards": {},
                "currency": {}
            },
            "countryCode": "ca",
            "loginCount": 16,
            "emailAddress": "test@email.com",
            "previousLogin": 1464621979514,
            "incoming_events": [],
            "lastLogin": 1464621990118,
            "languageCode": "en",
            "pictureUrl": null,
            "sessionId": "v3grtg3ve0a089pekk8lneuk8k",
            "amountSpent": 0
        }
    }
    

    Authenticate the user with brainCloud using their Facebook Credentials.

    Service Operation
    "authenticationV2" "AUTHENTICATE"
    Method Parameters
    Parameter Description
    facebookId The Facebook ID of the user
    facebookToken The validated token from the Facebook SDK
    forceCreate Should a new profile be created for this user if the account does not exist?
    Error returns
    Code Name Description
    40206 MISSING_IDENTITY_ERROR The identity does not exist on the server and forceCreate was false [and a profileId was provided - otherwise 40208 would have been returned]. Will also occur when forceCreate is true and a saved [but un-associated] profileId is provided. The error handler should reset the stored profile id (if there is one) and re-authenticate, setting forceCreate to true to create a new account. A common cause of this error is deleting the user's account via the Design Portal.
    40207 SWITCHING_PROFILES Indicates that the identity credentials are valid, and the saved profileId is valid, but the identity is not associated with the provided profileId. This may indicate that the user wants to switch accounts in the app. Often an app will pop-up a dialog confirming that the user wants to switch accounts, and then reset the stored profileId and call authenticate again.
    40208 MISSING_PROFILE_ERROR Returned when the identity cannot be located, no profileId is provided, and forceCreate is false. The normal response is to call Authenticate again with forceCreate set to true.
    40217 UNKNOWN_AUTH_ERROR An unknown error has occurred during authentication.
    40307 TOKEN_DOES_NOT_MATCH_USER The user credentials are invalid (i.e. bad Facebook id / token). May also indicate that Facebook integration is not properly configured.

    AuthenticateGameCenter

    string gameCenterId = "userGameCenterId";
    bool forceCreate = true;
    
    _bc.AuthenticationService.AuthenticateGameCenter(
        gameCenterId, forceCreate, SuccessCallback, FailureCallback);
    
    const char* gameCenterId = "userGameCenterId";
    bool forceCreate = true;
    
    _bc->getAuthenticationService()->authenticateGameCenter(
        gameCenterId,
        forceCreate,
        this);
    
    NSString * gameCenterID = @"userGameCenterId";
    BOOL forceCreate = true;
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [[_bc authenticationService]
             authenticateGameCenter:gameCenterID
                        forceCreate:forceCreate
                    completionBlock:successBlock
               errorCompletionBlock:failureBlock
                           cbObject:nil];
    
    // N/A
    
    var gameCenterID = "userGameCenterId";
    var forceCreate = true;
    
    _bc.authentication.authenticateGameCenter(gameCenterID, forceCreate, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    // N/A
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": {
            "vcPurchased": 0,
            "experiencePoints": 100,
            "refundCount": 0,
            "playerSessionExpiry": 60,
            "server_time": 1464621990155,
            "experienceLevel": 0,
            "currency": {
                "credits": {
                    "purchased": 0,
                    "balance": 12211,
                    "consumed": 133,
                    "awarded": 12344
                }
            },
            "abTestingId": 8,
            "statistics": {
                "gamesWon": 0
            },
            "id": "323e861-b749-4ce4-a57a-175232e21b5d",
            "createdAt": 1459439058035,
            "profileId": "323e861-b749-4ce4-a57a-175232e21b5d",
            "newUser": "false",
            "xpCapped": false,
            "sent_events": [],
            "timeZoneOffset": -5,
            "playerName": "",
            "vcClaimed": 0,
            "parentProfileId": null,
            "rewards": {
                "rewardDetails": {},
                "rewards": {},
                "currency": {}
            },
            "countryCode": "ca",
            "loginCount": 16,
            "emailAddress": "test@email.com",
            "previousLogin": 1464621979514,
            "incoming_events": [],
            "lastLogin": 1464621990118,
            "languageCode": "en",
            "pictureUrl": null,
            "sessionId": "v3grtg3ve0a089pekk8lneuk8k",
            "amountSpent": 0
        }
    }
    

    Authenticate the user using their Game Center ID.

    Service Operation
    "authenticationV2" "AUTHENTICATE"
    Method Parameters
    Parameter Description
    gameCenterId The player's game center ID (use the playerID property from the local GKPlayer object)
    forceCreate Should a new profile be created for this user if the account does not exist?
    Error returns
    Code Name Description
    40206 MISSING_IDENTITY_ERROR The identity does not exist on the server and forceCreate was false [and a profileId was provided - otherwise 40208 would have been returned]. Will also occur when forceCreate is true and a saved [but un-associated] profileId is provided. The error handler should reset the stored profile id (if there is one) and re-authenticate, setting forceCreate to true to create a new account. A common cause of this error is deleting the user's account via the design portal.
    40207 SWITCHING_PROFILES Indicates that the identity credentials are valid, and the saved profileId is valid, but the identity is not associated with the provided profileId. This may indicate that the user wants to switch accounts in the app. Often an app will pop-up a dialog confirming that the user wants to switch accounts, and then reset the stored profileId and call authenticate again.
    40208 MISSING_PROFILE_ERROR Returned when the identity cannot be located, no profileId is provided, and forceCreate is false. The normal response is to call Authenticate again with forceCreate set to true.
    40217 UNKNOWN_AUTH_ERROR An unknown error has occurred during authentication.
    40307 TOKEN_DOES_NOT_MATCH_USER The user credentials are invalid (i.e. bad gameCenterId)

    AuthenticateGoogle

    string googleId = "idFromGoogle";
    string googleToken = "authTokenFromGoogle";
    bool forceCreate = true;
    
    _bc.AuthenticationService.AuthenticateGoogle(
        googleId, googleToken, forceCreate, SuccessCallback, FailureCallback);
    
    const char* googleId = "idFromGoogle";
    const char* googleToken = "authTokenFromGoogle";
    bool forceCreate = true;
    
    _bc->getAuthenticationService()->authenticateGoogle(
        googleId, googleToken, forceCreate, this);
    
    NSString * googleId = @"idFromGoogle";
    NSString * googleToken = @"authTokenFromGoogle";
    BOOL forceCreate = true;
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [[_bc authenticationService]
             authenticateGoogle:googleId
            authenticationToken:googleToken
                    forceCreate:forceCreate
                completionBlock:successBlock
           errorCompletionBlock:failureBlock
                       cbObject:nil];
    
    String googleId = "idFromGoogle";
    String googleToken = "authTokenFromGoogle";
    boolean forceCreate = true;
    this; // implements IServerCallback
    
    _bc.getAuthenticationService().authenticateGoogle(googleId, googleToken, forceCreate, this);
    
    public void serverCallback(ServiceName serviceName, ServiceOperation serviceOperation, JSONObject jsonData)
    {
        System.out.print(String.format("Success | %s", jsonData.toString()));
    }
    public void serverError(ServiceName serviceName, ServiceOperation serviceOperation, int statusCode, int reasonCode, String jsonError)
    {
        System.out.print(String.format("Failed | %d %d %s", statusCode,  reasonCode, jsonError.toString()));
    }
    
    var googleId = "idFromGoogle";
    var googleToken = "authTokenFromGoogle";
    var forceCreate = true;
    
    _bc.authentication.authenticateFacebook(googleId, googleToken, forceCreate, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    // N/A
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": {
            "vcPurchased": 0,
            "experiencePoints": 100,
            "refundCount": 0,
            "playerSessionExpiry": 60,
            "server_time": 1464621990155,
            "experienceLevel": 0,
            "currency": {
                "credits": {
                    "purchased": 0,
                    "balance": 12211,
                    "consumed": 133,
                    "awarded": 12344
                }
            },
            "abTestingId": 8,
            "statistics": {
                "gamesWon": 0
            },
            "id": "323e861-b749-4ce4-a57a-175232e21b5d",
            "createdAt": 1459439058035,
            "profileId": "323e861-b749-4ce4-a57a-175232e21b5d",
            "newUser": "false",
            "xpCapped": false,
            "sent_events": [],
            "timeZoneOffset": -5,
            "playerName": "",
            "vcClaimed": 0,
            "parentProfileId": null,
            "rewards": {
                "rewardDetails": {},
                "rewards": {},
                "currency": {}
            },
            "countryCode": "ca",
            "loginCount": 16,
            "emailAddress": "test@email.com",
            "previousLogin": 1464621979514,
            "incoming_events": [],
            "lastLogin": 1464621990118,
            "languageCode": "en",
            "pictureUrl": null,
            "sessionId": "v3grtg3ve0a089pekk8lneuk8k",
            "amountSpent": 0
        }
    }
    

    Authenticate the user using a google user ID (email address) and google authentication token.

    Service Operation
    "authenticationV2" "AUTHENTICATE"
    Method Parameters
    Parameter Description
    googleId String representation of google+ userid (email)
    googleToken The authentication token derived via the google apis.
    forceCreate Should a new profile be created for this user if the account does not exist?
    Error returns
    Code Name Description
    40206 MISSING_IDENTITY_ERROR The identity does not exist on the server and forceCreate was false [and a profileId was provided - otherwise 40208 would have been returned]. Will also occur when forceCreate is true and a saved [but un-associated] profileId is provided. The error handler should reset the stored profile id (if there is one) and re-authenticate, setting forceCreate to true to create a new account. A common cause of this error is deleting the user's account via the Design Portal.
    40207 SWITCHING_PROFILES Indicates that the identity credentials are valid, and the saved profileId is valid, but the identity is not associated with the provided profileId. This may indicate that the user wants to switch accounts in the app. Often an app will pop-up a dialog confirming that the user wants to switch accounts, and then reset the stored profileId and call authenticate again.
    40208 MISSING_PROFILE_ERROR Returned when the identity cannot be located, no profileId is provided, and forceCreate is false. The normal response is to call Authenticate again with forceCreate set to true.
    40217 UNKNOWN_AUTH_ERROR An unknown error has occurred during authentication.
    40307 TOKEN_DOES_NOT_MATCH_USER The user credentials are invalid (i.e. googleId and googleToken are invalid). May also indicate that Google Integration is not properly configured.

    AuthenticateHandoff

    string handoffId = "handoffId";
    string secruityToken = "secruityToken";
    bool forceCreate = true;
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("Success | {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("Failed | {0}  {1}  {2}", status, code, error));
    };
    
    _bc.AuthenticationService.AuthenticateHandoff(
        handoffId, secruityToken, forceCreate, successCallback, failureCallback);
    
    const char* handoffId = "handoffId";
    const char* secruityToken = "secruityToken";
    bool forceCreate = true;
    
    _bc->getAuthenticationService()->authenticateHandoff(
        handoffId,
        secruityToken,
        forceCreate,
        this);
    
    NSString* handoffId = @"handoffId";
    NSString* secruityToken = @"secruityToken";
    BOOL forceCreate = true;
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [[_bc authenticationService]
            authenticateHandoff:handoffId
                  secruityToken:secruityToken
                    forceCreate:forceCreate
                completionBlock:successBlock
           errorCompletionBlock:failureBlock
                       cbObject:nil];
    
    String handoffId = "handoffId";
    String secruityToken = "secruityToken";
    boolean forceCreate = true;
    this; // implements IServerCallback
    
    _bc.getAuthenticationService().authenticateHandoff(handoffId, secruityToken, forceCreate, this);
    
    public void serverCallback(ServiceName serviceName, ServiceOperation serviceOperation, JSONObject jsonData)
    {
        System.out.print(String.format("Success | %s", jsonData.toString()));
    }
    public void serverError(ServiceName serviceName, ServiceOperation serviceOperation, int statusCode, int reasonCode, String jsonError)
    {
        System.out.print(String.format("Failed | %d %d %s", statusCode,  reasonCode, jsonError.toString()));
    }
    
    var handoffId = "handoffId";
    var secruityToken = "secruityToken";
    var forceCreate = true;
    
    _bc.authentication.authenticateHandoff(handoffId, secruityToken, forceCreate, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    // N/A
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": {
            "vcPurchased": 0,
            "experiencePoints": 100,
            "refundCount": 0,
            "playerSessionExpiry": 60,
            "server_time": 1464621990155,
            "experienceLevel": 0,
            "currency": {
                "credits": {
                    "purchased": 0,
                    "balance": 12211,
                    "consumed": 133,
                    "awarded": 12344
                }
            },
            "abTestingId": 8,
            "statistics": {
                "gamesWon": 0
            },
            "id": "323e861-b749-4ce4-a57a-175232e21b5d",
            "createdAt": 1459439058035,
            "profileId": "323e861-b749-4ce4-a57a-175232e21b5d",
            "newUser": "false",
            "xpCapped": false,
            "sent_events": [],
            "timeZoneOffset": -5,
            "playerName": "",
            "vcClaimed": 0,
            "parentProfileId": null,
            "rewards": {
                "rewardDetails": {},
                "rewards": {},
                "currency": {}
            },
            "countryCode": "ca",
            "loginCount": 16,
            "emailAddress": "test@email.com",
            "previousLogin": 1464621979514,
            "incoming_events": [],
            "lastLogin": 1464621990118,
            "languageCode": "en",
            "pictureUrl": null,
            "sessionId": "v3grtg3ve0a089pekk8lneuk8k",
            "amountSpent": 0
        }
    }
    

    Authenticate the user with a custom Authentication Handoff.

    Service Operation
    "authenticationV2" "AUTHENTICATE"
    Method Parameters
    Parameter Description
    handoffId The id for the given handoff
    secruityToken The secruity token used to verify the handoff
    forceCreate Should a new profile be created for this user if the account does not exist?
    Show Example Error Handling {}
    public void FailureCallback(int statusCode, int reasonCode, string statusMessage, object cbObject) {
        switch (reasonCode) {
            case ReasonCodes.MISSING_IDENTITY_ERROR: { // Identity does not exist (and client has orphaned profileId)
    
                // Reset profileId and re-authenticate
                BrainCloudClient.Get().AuthenticationService.ResetStoredProfileId();
                BrainCloudClient.Get().AuthenticationService.AuthenticateEmail(email, password, true);
                break;
            }
            case ReasonCodes.SWITCHING_PROFILES: { // Identity belongs to a different profile
    
                // Reset profileId and re-authenticate
                BrainCloudClient.Get().AuthenticationService.ResetStoredProfileId();
                BrainCloudClient.Get().AuthenticationService.AuthenticateEmail(email, password, forceCreate);
                break;
            }
            case ReasonCodes.MISSING_PROFILE_ERROR: { // Identity does not exist
    
                // The account doesn't exist - create it now.
                BrainCloudClient.Get().AuthenticationService.AuthenticateEmail(email, password, true);
                break;
            }
            case ReasonCodes.TOKEN_DOES_NOT_MATCH_USER: { // User auth information is incorrect
    
                // Display a dialog telling the user that the password provided was invalid,
                // and invite them to re-enter the password.
                // ...
                break;
            }
            default: { // Uncaught reasonCode
    
                // Log the error for debugging later
                // ...
                break;
            }
        }
    }
    
    Error returns
    Code Name Description
    40206 MISSING_IDENTITY_ERROR The identity does not exist on the server and forceCreate was false [and a profileId was provided - otherwise 40208 would have been returned]. Will also occur when forceCreate is true and a saved [but un-associated] profileId is provided. The error handler should reset the stored profile id (if there is one) and re-authenticate, setting forceCreate to true to create a new account. A common cause of this error is deleting the user's account via the Design Portal.
    40207 SWITCHING_PROFILES Indicates that the identity credentials are valid, and the saved profileId is valid, but the identity is not associated with the provided profileId. This may indicate that the user wants to switch accounts in the app. Most often an app will pop-up a dialog confirming that the user wants to switch accounts, and then reset the stored profileId and call authenticate again.
    40208 MISSING_PROFILE_ERROR Returned when the identity cannot be located, no profileId is provided, and forceCreate is false. The normal response is to call Authenticate again with forceCreate set to true.
    40217 UNKNOWN_AUTH_ERROR An unknown error has occurred during authentication.
    40307 TOKEN_DOES_NOT_MATCH_USER The user's password is incorrect.

    AuthenticateParse

    string parseId = "someId1234";
    string token = "authToken";
    bool forceCreate = true;
    
    _bc.AuthenticationService.AuthenticateParse(
        parseId, token, forceCreate, SuccessCallback, FailureCallback);
    
    const char* parseId = "someId1234";
    const char* token = "authToken";
    bool forceCreate = true;
    
    _bc->getAuthenticationService()->authenticateParse(
        parseId, token, forceCreate, this);
    
    NSString * userID = @"someId1234";
    NSString * authToken = @"authToken";
    BOOL forceCreate = true;
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [[_bc authenticationService]
              authenticateParse:userID
                          token:authToken
                    forceCreate:forceCreate
                completionBlock:successBlock
           errorCompletionBlock:failureBlock
                       cbObject:nil];
    
    String parseUserId = "someId1234";
    String parseAuthToken = "authToken";
    boolean forceCreate = true;
    this; // implements IServerCallback
    
    _bc.getAuthenticationService().authenticateParse(googleId, googleToken, forceCreate, this);
    
    public void serverCallback(ServiceName serviceName, ServiceOperation serviceOperation, JSONObject jsonData)
    {
        System.out.print(String.format("Success | %s", jsonData.toString()));
    }
    public void serverError(ServiceName serviceName, ServiceOperation serviceOperation, int statusCode, int reasonCode, String jsonError)
    {
        System.out.print(String.format("Failed | %d %d %s", statusCode,  reasonCode, jsonError.toString()));
    }
    
    var parseUserId = "someId1234";
    var parseAuthToken = "authToken";
    var forceCreate = true;
    
    _bc.authentication.authenticateParse(googleId, googleToken, forceCreate, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    // N/A
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": {
            "vcPurchased": 0,
            "experiencePoints": 100,
            "refundCount": 0,
            "playerSessionExpiry": 60,
            "server_time": 1464621990155,
            "experienceLevel": 0,
            "currency": {
                "credits": {
                    "purchased": 0,
                    "balance": 12211,
                    "consumed": 133,
                    "awarded": 12344
                }
            },
            "abTestingId": 8,
            "statistics": {
                "gamesWon": 0
            },
            "id": "323e861-b749-4ce4-a57a-175232e21b5d",
            "createdAt": 1459439058035,
            "profileId": "323e861-b749-4ce4-a57a-175232e21b5d",
            "newUser": "false",
            "xpCapped": false,
            "sent_events": [],
            "timeZoneOffset": -5,
            "playerName": "",
            "vcClaimed": 0,
            "parentProfileId": null,
            "rewards": {
                "rewardDetails": {},
                "rewards": {},
                "currency": {}
            },
            "countryCode": "ca",
            "loginCount": 16,
            "emailAddress": "test@email.com",
            "previousLogin": 1464621979514,
            "incoming_events": [],
            "lastLogin": 1464621990118,
            "languageCode": "en",
            "pictureUrl": null,
            "sessionId": "v3grtg3ve0a089pekk8lneuk8k",
            "amountSpent": 0
        }
    }
    

    Authenticate the user using a Parse user ID and authentication token.

    Service Operation
    "authenticationV2" "AUTHENTICATE"
    Method Parameters
    Parameter Description
    parseId String representation of Parse user ID
    parseToken The authentication token from Parse
    forceCreate Should a new profile be created for this user if the account does not exist?
    Error returns
    Code Name Description
    40206 MISSING_IDENTITY_ERROR The identity does not exist on the server and forceCreate was false [and a profileId was provided - otherwise 40208 would have been returned]. Will also occur when forceCreate is true and a saved [but un-associated] profileId is provided. The error handler should reset the stored profile id (if there is one) and re-authenticate, setting forceCreate to true to create a new account. A common cause of this error is deleting the user's account via the Design Portal.
    40207 SWITCHING_PROFILES Indicates that the identity credentials are valid, and the saved profileId is valid, but the identity is not associated with the provided profileId. This may indicate that the user wants to switch accounts in the app. Often an app will pop-up a dialog confirming that the user wants to switch accounts, and then reset the stored profileId and call authenticate again.
    40208 MISSING_PROFILE_ERROR Returned when the identity cannot be located, no profileId is provided, and forceCreate is false. The normal response is to call Authenticate again with forceCreate set to true.
    40217 UNKNOWN_AUTH_ERROR An unknown error has occurred during authentication.
    40307 TOKEN_DOES_NOT_MATCH_USER The user credentials are invalid (i.e. parseId and parseToken are invalid). May also indicate that Parse Integration is not properly configured.

    AuthenticateSteam

    string steamId = "userSteamId";
    string sessionTicket = "sessionTicketFromSteam";
    bool forceCreate = true;
    
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Success] {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Failed] {0}  {1}  {2}", status, code, error));
    };
    _bc.AuthenticationService.AuthenticateSteam(
        steamId, tisessionTicketcket, forceCreate,
        successCallback, failureCallback);
    
    const char* steamId = "userSteamId";
    const char* sessionTicket = "sessionTicketFromSteam";
    
    _bc->getAuthenticationService()->authenticateSteam(
        steamId, sessionTicket, true, this);
    
    NSString * steamId = @"userSteamId";
    NSString * sessionTicket = @"sessionTicketFromSteam";
    BOOL forceCreate = true;
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [[_bc authenticationService]
              authenticateSteam:steamId
                  sessionTicket:sessionTicket
                    forceCreate:forceCreate
                completionBlock:successBlock
           errorCompletionBlock:failureBlock
                       cbObject:nil];
    
    String steamId = "userSteamId";
    String sessionTicket = "sessionTicketFromSteam";
    boolean forceCreate = true;
    this; // implements IServerCallback
    
    _bc.getAuthenticationService().authenticateSteam(steamId, sessionTicket, forceCreate, this);
    
    public void serverCallback(ServiceName serviceName, ServiceOperation serviceOperation, JSONObject jsonData)
    {
        System.out.print(String.format("Success | %s", jsonData.toString()));
    }
    public void serverError(ServiceName serviceName, ServiceOperation serviceOperation, int statusCode, int reasonCode, String jsonError)
    {
        System.out.print(String.format("Failed | %d %d %s", statusCode,  reasonCode, jsonError.toString()));
    }
    
    var steamId = "userSteamId";
    var sessionTicket = "sessionTicketFromSteam";
    var forceCreate = true;
    
    _bc.authentication.authenticateSteam(steamId, sessionTicket, forceCreate, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    // N/A
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": {
            "vcPurchased": 0,
            "experiencePoints": 100,
            "refundCount": 0,
            "playerSessionExpiry": 60,
            "server_time": 1464621990155,
            "experienceLevel": 0,
            "currency": {
                "credits": {
                    "purchased": 0,
                    "balance": 12211,
                    "consumed": 133,
                    "awarded": 12344
                }
            },
            "abTestingId": 8,
            "statistics": {
                "gamesWon": 0
            },
            "id": "323e861-b749-4ce4-a57a-175232e21b5d",
            "createdAt": 1459439058035,
            "profileId": "323e861-b749-4ce4-a57a-175232e21b5d",
            "newUser": "false",
            "xpCapped": false,
            "sent_events": [],
            "timeZoneOffset": -5,
            "playerName": "",
            "vcClaimed": 0,
            "parentProfileId": null,
            "rewards": {
                "rewardDetails": {},
                "rewards": {},
                "currency": {}
            },
            "countryCode": "ca",
            "loginCount": 16,
            "emailAddress": "test@email.com",
            "previousLogin": 1464621979514,
            "incoming_events": [],
            "lastLogin": 1464621990118,
            "languageCode": "en",
            "pictureUrl": null,
            "sessionId": "v3grtg3ve0a089pekk8lneuk8k",
            "amountSpent": 0
        }
    }
    

    Authenticate the user using a steam userId and session ticket (without any validation on the userId).

    Service Operation
    "authenticationV2" "AUTHENTICATE"
    Method Parameters
    Parameter Description
    userId String representation of 64 bit steam ID
    sessionTicket The session ticket of the user (hex encoded)
    forceCreate Should a new profile be created for this user if the account does not exist?
    Error returns
    Code Name Description
    40206 MISSING_IDENTITY_ERROR The identity does not exist on the server and forceCreate was false [and a profileId was provided - otherwise 40208 would have been returned]. Will also occur when forceCreate is true and a saved [but un-associated] profileId is provided. The error handler should reset the stored profile id (if there is one) and re-authenticate, setting forceCreate to true to create a new account. A common cause of this error is deleting the user's account via the Design Portal.
    40207 SWITCHING_PROFILES Indicates that the identity credentials are valid, and the saved profileId is valid, but the identity is not associated with the provided profileId. This may indicate that the user wants to switch accounts in the app. Often an app will pop-up a dialog confirming that the user wants to switch accounts, and then reset the stored profileId and call authenticate again.
    40208 MISSING_PROFILE_ERROR Returned when the identity cannot be located, no profileId is provided, and forceCreate is false. The normal response is to call Authenticate again with forceCreate set to true.
    40217 UNKNOWN_AUTH_ERROR An unknown error has occurred during authentication.
    40307 TOKEN_DOES_NOT_MATCH_USER The user credentials are invalid (i.e. bad Steam userId and/or sessionTicket). May also indicate that Steam Integration is not properly configured.

    AuthenticateTwitter

    string twitterId = "userTwitterId";
    string token = "userAuthToken";
    string secret = "secretFromTwitterApi";
    bool forceCreate = true;
    
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Success] {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("[Authenticate Failed] {0}  {1}  {2}", status, code, error));
    };
    _bc.AuthenticationService.AuthenticateTwitter(
        twitterId, token, secret, forceCreate,
        successCallback, failureCallback);
    
    const char* twitterId = "userTwitterId";
    const char* token = "userAuthToken";
    const char* secret = "secretFromTwitterApi";
    bool forceCreate = true;
    
    _bc->getAuthenticationService()->authenticateTwitter(
        twitterId, token, secret, forceCreate, this);
    
    NSString * twitterId = @"userTwitterId";
    NSString * token = @"userAuthToken";
    NSString * secret = @"secretFromTwitterApi";
    BOOL forceCreate = true;
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [[_bc authenticationService]
            authenticateTwitter:twitterId
                          token:token
                          secret:secret
                     forceCreate:forceCreate
                 completionBlock:successBlock
            errorCompletionBlock:failureBlock
                        cbObject:nil];
    
    String twitterId = "userTwitterId";
    String token = "userAuthToken";
    String secret = "secretFromTwitterApi";
    boolean forceCreate = true;
    this; // implements IServerCallback
    
    _bc.getAuthenticationService().authenticateTwitter(twitterId, token, secret, forceCreate, this);
    
    public void serverCallback(ServiceName serviceName, ServiceOperation serviceOperation, JSONObject jsonData)
    {
        System.out.print(String.format("Success | %s", jsonData.toString()));
    }
    public void serverError(ServiceName serviceName, ServiceOperation serviceOperation, int statusCode, int reasonCode, String jsonError)
    {
        System.out.print(String.format("Failed | %d %d %s", statusCode,  reasonCode, jsonError.toString()));
    }
    
    var twitterId = "userTwitterId";
    var token = "userAuthToken";
    var secret = "secretFromTwitterApi";
    var forceCreate = true;
    
    _bc.authentication.authenticateTwitter(twitterId, token, secret, forceCreate, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    // N/A
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": {
            "vcPurchased": 0,
            "experiencePoints": 100,
            "refundCount": 0,
            "playerSessionExpiry": 60,
            "server_time": 1464621990155,
            "experienceLevel": 0,
            "currency": {
                "credits": {
                    "purchased": 0,
                    "balance": 12211,
                    "consumed": 133,
                    "awarded": 12344
                }
            },
            "abTestingId": 8,
            "statistics": {
                "gamesWon": 0
            },
            "id": "323e861-b749-4ce4-a57a-175232e21b5d",
            "createdAt": 1459439058035,
            "profileId": "323e861-b749-4ce4-a57a-175232e21b5d",
            "newUser": "false",
            "xpCapped": false,
            "sent_events": [],
            "timeZoneOffset": -5,
            "playerName": "",
            "vcClaimed": 0,
            "parentProfileId": null,
            "rewards": {
                "rewardDetails": {},
                "rewards": {},
                "currency": {}
            },
            "countryCode": "ca",
            "loginCount": 16,
            "emailAddress": "test@email.com",
            "previousLogin": 1464621979514,
            "incoming_events": [],
            "lastLogin": 1464621990118,
            "languageCode": "en",
            "pictureUrl": null,
            "sessionId": "v3grtg3ve0a089pekk8lneuk8k",
            "amountSpent": 0
        }
    }
    

    Authenticate the user using a Twitter user ID, authentication token, and secret from Twitter.

    Service Operation
    "authenticationV2" "AUTHENTICATE"
    Method Parameters
    Parameter Description
    twitterId String representation of Twitter user ID
    token The authentication token derived via the Twitter APIs
    secret The secret given when attempting to link with Twitter
    forceCreate Should a new profile be created for this user if the account does not exist?
    Error returns
    Code Name Description
    40206 MISSING_IDENTITY_ERROR The identity does not exist on the server and forceCreate was false [and a profileId was provided - otherwise 40208 would have been returned]. Will also occur when forceCreate is true and a saved [but un-associated] profileId is provided. The error handler should reset the stored profile id (if there is one) and re-authenticate, setting forceCreate to true to create a new account. A common cause of this error is deleting the user's account via the Design Portal.
    40207 SWITCHING_PROFILES Indicates that the identity credentials are valid, and the saved profileId is valid, but the identity is not associated with the provided profileId. This may indicate that the user wants to switch accounts in the app. Often an app will pop-up a dialog confirming that the user wants to switch accounts, and then reset the stored profileId and call authenticate again.
    40208 MISSING_PROFILE_ERROR Returned when the identity cannot be located, no profileId is provided, and forceCreate is false. The normal response is to call Authenticate again with forceCreate set to true.
    40217 UNKNOWN_AUTH_ERROR An unknown error has occurred during authentication.
    40307 TOKEN_DOES_NOT_MATCH_USER The user credentials are invalid (i.e. bad Twitter userId / token / secret). May also indicate that Twitter integration is not properly configured.

    AuthenticateUniversal

    const char* userId = "Username";
    const char* password = "passwrd123";
    bool foreCreate = true;
    
    _bc->getAuthenticationService()->authenticateUniversal(userId, password, foreCreate, this);
    
    string userId = "Username";
    string password = "passwrd123";
    bool forceCreate = true;
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("Success | {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("Failed | {0}  {1}  {2}", status, code, error));
    };
    
    _bc.AuthenticationService.AuthenticateUniversal(userId, password, forceCreate, successCallback, failureCallback);
    
    String userId = "Username";
    String userId = "passwrd123";
    boolean forceCreate = true;
    this; // implements IServerCallback
    
    BrainCloudClient.GetAuthenticationService().AuthenticateUniversal(userId, password, forceCreate, this);
    
    public void serverCallback(ServiceName serviceName, ServiceOperation serviceOperation, JSONObject jsonData)
    {
        System.out.print(String.format("Success | %s", jsonData.toString()));
    }
    public void serverError(ServiceName serviceName, ServiceOperation serviceOperation, int statusCode, int reasonCode, String jsonError)
    {
        System.out.print(String.format("Failed | %d %d %s", statusCode,  reasonCode, jsonError.toString()));
    }
    
    NSString* userId = @"UserId";
    NSString* password = @"password";
    BOOL forceCreate = true;
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [[_bc authenticationService]
        authenticateUniversal:userId
                     password:password
                  forceCreate:forceCreate
              completionBlock:successBlock
         errorCompletionBlock:failureBlock
                     cbObject:nil];
    
    var userId = "UserId";
    var password = "password";
    var forceCreate = true;
    
    _bc.authentication.authenticateUniversal(userId, password, forceCreate, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": {
            "vcPurchased": 0,
            "experiencePoints": 100,
            "refundCount": 0,
            "playerSessionExpiry": 60,
            "server_time": 1464621990155,
            "experienceLevel": 0,
            "currency": {
                "credits": {
                    "purchased": 0,
                    "balance": 12211,
                    "consumed": 133,
                    "awarded": 12344
                }
            },
            "abTestingId": 8,
            "statistics": {
                "gamesWon": 0
            },
            "id": "323e861-b749-4ce4-a57a-175232e21b5d",
            "createdAt": 1459439058035,
            "profileId": "323e861-b749-4ce4-a57a-175232e21b5d",
            "newUser": "false",
            "xpCapped": false,
            "sent_events": [],
            "timeZoneOffset": -5,
            "playerName": "",
            "vcClaimed": 0,
            "parentProfileId": null,
            "rewards": {
                "rewardDetails": {},
                "rewards": {},
                "currency": {}
            },
            "countryCode": "ca",
            "loginCount": 16,
            "emailAddress": "test@email.com",
            "previousLogin": 1464621979514,
            "incoming_events": [],
            "lastLogin": 1464621990118,
            "languageCode": "en",
            "pictureUrl": null,
            "sessionId": "v3grtg3ve0a089pekk8lneuk8k",
            "amountSpent": 0
        }
    }
    

    Universal authentication allows the developer to pass in any user/password string combination. As with all authentication methods, if the create new profile flag is specified as false, the authentication will fail if the user/password combination does not match a user in the database.

    Service Operation
    "authenticationV2" "AUTHENTICATE"
    Method Parameters
    Parameter Description
    userId The user's ID.
    password The password of the user.
    forceCreate If set to true, create a new profile if userId not found. If set to false and anonymous ID does not exist on the server, return an error.
    Show Example Error Handling {}
    public void FailureCallback(int statusCode, int reasonCode, string statusMessage, object cbObject) {
        switch (reasonCode) {
            case ReasonCodes.MISSING_IDENTITY_ERROR: { // Identity does not exist (and client has orphaned profileId)
    
                // Reset profileId and re-authenticate
                BrainCloudClient.Get().AuthenticationService.ResetStoredProfileId();
                BrainCloudClient.Get().AuthenticationService.AuthenticateUniversal(userId, password, true);
                break;
            }
            case ReasonCodes.SWITCHING_PROFILES: { // Identity belongs to a different profile
    
                // [Optional] Prompt user to confirm that they wish to switch accounts?
    
                // Reset profileId and re-authenticate
                BrainCloudClient.Get().AuthenticationService.ResetStoredProfileId();
                BrainCloudClient.Get().AuthenticationService.AuthenticateUniversal(userId, password, forceCreate);
                break;
            }
            case ReasonCodes.MISSING_PROFILE_ERROR: { // Identity does not exist
    
                // The account doesn't exist - create it now.
                BrainCloudClient.Get().AuthenticationService.AuthenticateUniversal(userId, password, true);
                break;
            }
            case ReasonCodes.TOKEN_DOES_NOT_MATCH_USER: { // Wrong password
    
                // Display a dialog telling the user that the password provided was invalid,
                // and invite them to re-enter the password.
                // ...
                break;
            }
            default: { // Uncaught reasonCode
    
                // Log the error for debugging later
                // ...
                break;
            }
        }
    }
    
    Error returns
    Code Name Description
    40206 MISSING_IDENTITY_ERROR The identity does not exist on the server and forceCreate was false [and a profileId was provided - otherwise 40208 would have been returned]. Will also occur when forceCreate is true and a saved [and unrelated] profileId is provided. The error handler should reset the stored profile id (if there is one) and re-authenticate, setting forceCreate to true to create a new account. A common cause of this error is deleting the user's account via the Design Portal.
    40207 SWITCHING_PROFILES Indicates that the identity credentials are valid, and the saved profileId is valid, but the identity is not associated with the profileId. This may indicate that the user wants to switch accounts in the app. Often an app will pop-up a dialog confirming that the user wants to switch accounts, and then reset the stored profileId and call authenticate again.
    40208 MISSING_PROFILE_ERROR Returned when the identity cannot be located, no profileId is provided, and forceCreate is false. The normal response is to call Authenticate again with forceCreate set to true.
    40217 UNKNOWN_AUTH_ERROR An unknown error has occurred during authentication.
    40307 TOKEN_DOES_NOT_MATCH_USER The user credentials don't match (i.e. incorrect password).

    ClearSavedProfileId

    _bc.AuthenticationService.ClearSavedProfileID();
    
    _bc->getAuthenticationService()->clearSavedProfileID();
    
    [[_bc authenticationService] clearSavedProfile];
    
    public void clearSavedProfileId();
    
    _bc.authentication.clearSavedProfileId();
    
    // N/A
    

    Used to clear the saved profile ID - to use in cases when the user is attempting to switch to a different game profile.

    GenerateAnonymousId

    string anonId = _bc.AuthenticationService.GenerateAnonymousId();
    
    std::string anonId = _bc->getAuthenticationService()->generateAnonymousId();
    
    NSString * anonId = [[_bc authenticationService] generateAnonymousId];
    
    String anonId = _bc.getAuthenticationService().generateAnonymousId();
    
    var anonId = _bc.authentication.generateAnonymousId();
    
    // N/A
    

    Generates a GUID for use as an anonymous installation ID for brainCloud. Normally only called once when the application starts for the first time.

    The generated ID is used in conjunction with InitializeIdentity in the BrainCloudClient.

    Initialize

    _bc.AuthenticationService.Initialize("profileId", "anonId");
    
    _bc->getAuthenticationService()->initialize("profileId", "anonId");
    
    NSString * profileID = @"profileId";
    NSString * anonymousID = @"anonId";
    
    [[_bc authenticationService]
                    initialize:profileID
                   anonymousID:anonymousID];
    
    public void initialize(String profileId, String anonymousId);
    
    _bc.authentication.initialize(profileId, anonymousId);
    
    // N/A
    

    Initializes the authentication service with an anonymous installation ID and most recently used profile ID. You will need to call this method before authenticating anonymously.

    Note that calling this is the same as calling InitializeIdentity in the BrainCloudClient.

    Method Parameters
    Parameter Description
    profileId The ID of the profile ID that was most recently used by the app (on this device)
    anonymousId The anonymous installation ID that was generated for this device

    ResetEmailPassword

    string email = "userEmail@somedomain.com";
    
    _bc.AuthenticationService.ResetEmailPassword(
        email, ApiSuccess, ApiError)
    
    const char* email = "userEmail@somedomain.com";
    
    _bc->getAuthenticationService()->resetEmailPassword(email, this);
    
    NSString * email = @"userEmail@somedomain.com";
    
    [[_bc authenticationService]
                 resetEmailPassword:email
                    completionBlock:successBlock
                   errorCompletionBlock:failureBlock
                               cbObject:nil];
    
    public void resetEmailPassword(String email, IAuthenticationServiceCallback callback)
    
    _bc.authentication.resetEmailPassword = function(email, responseHandler)
    
    // N/A
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": null
    }
    

    Sends a password reset email to the specified address.

    Service Operation
    "authenticationV2" "RESET_EMAIL_PASSWORD"
    Method Parameters
    Parameter Description
    email The email address to send the reset email to.

    AppStore

    The AppStore Service provides access to Product / Pricing / Promotion features, as well as integrations with supported AppStores.

    This service replaces the deprecated Product Service for purchases and product / pricing data. Currency operations have been moved to the new VirtualCurrency Service.

    It includes APIs for:

    Verifying In-app Purchases

    The specifics of processing in-app purchases from platform to platform vary slightly, but the overall flow is as follows:

    The follow call requests the list of products for sale:

    This method is used to confirm store receipts:

    Performing Two-part Purchases

    Some AppStores, like Steam, do a real-time two-part purchase. The following new API methods handle this requirement:

    Promotions

    In addition to the above purchase flows, the app can also query to see if any promotions are currently active (for display in banners, etc.), using the GetEligiblePromotions call – and can make manual adjustments to virtual currency balances.

    The promotions API(s) are:

    API Summary

    Verifying In-app Purchases

    The specifics of processing in-app purchases from platform to platform vary slightly, but the overall flow is as follows:

    The follow call requests the list of products for sale:

    This method is used to confirm store receipts:

    Performing Two-part Purchases

    Some AppStores, like Steam, do a real-time two-part purchase. The following new API methods handle this requirement:

    Promotions

    In addition to the above purchase flows, the app can also query to see if any promotions are currently active (for display in banners, etc.), using the GetEligiblePromotions call – and can make manual adjustments to virtual currency balances.

    The promotions API(s) are:

    FinalizePurchase

    const char *storeId = "itunes";
    const char *transactionId = "00002";
    const char *transactionData = "{\"transactionId\":\"3555\"}";
    
    _bc->getAppStore()->finalizePurchase(storeId, transactionId, transactionData, this);
    
    string storeId = "itunes";
    string transactionId = "00002";
    string transactionData = "{\"transactionId\":\"3555\"}";
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("Success | {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("Failed | {0}  {1}  {2}", status, code, error));
    };
    
    _bc.AppStore.FinalizePurchase(storeId, transactionId, transactionData, successCallback, failureCallback);
    
    // N/A
    
    // N/A
    
    // N/A
    
    var storeId = "itunes";
    var transactionId = "00002";
    var transactionData = {
        "transactionId": "3555"
    };
    var appStoreProxy = bridge.getAppStoreServiceProxy();
    
    var postResult = appStoreProxy.finalizePurchase(storeId, transactionId, transactionData);
    if (postResult.status == 200) {
        // Success!
    }
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": {
            "result": "OK"
        }
    }
    

    Finalize a purchase transaction. On success, the player will be awarded the associated currencies.

    Service Operation
    "appStore" "FINALIZE_PURCHASE"
    Method Parameters
    Parameter Description
    storeId Store type
    transactionId id of transaction to finalize
    transactionData Store-specific purchase data

    GetEligiblePromotions

    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [[_bc appStoreService] getEligiblePromotions:successBlock
           errorCompletionBlock:failureBlock
                       cbObject:nil];
    
    _bc->getAppStore()->getEligiblePromotions(this);
    
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("Success | {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("Failed | {0}  {1}  {2}", status, code, error));
    };
    
    _bc.AppStore.GetEligiblePromotions(successCallback, failureCallback);
    
    this; // implements IServerCallback
    
    _bc.getAppStore().getEligiblePromotions(this);
    
    public void serverCallback(ServiceName serviceName, ServiceOperation serviceOperation, JSONObject jsonData)
    {
        System.out.print(String.format("Success | %s", jsonData.toString()));
    }
    public void serverError(ServiceName serviceName, ServiceOperation serviceOperation, int statusCode, int reasonCode, String jsonError)
    {
        System.out.print(String.format("Failed | %d %d %s", statusCode,  reasonCode, jsonError.toString()));
    }
    
    _bc.appStore.getEligiblePromotions(result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    var appStoreProxy = bridge.getAppStoreServiceProxy();
    
    var postResult = appStoreProxy.getEligiblePromotions();
    if (postResult.status == 200) {
        // Success!
    }
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": {
            "promotions": [
                {
                    "gameId": "10019",
                    "promotionId": 9,
                    "type": "SCHEDULED",
                    "name": "session >= 2",
                    "message": "test1",
                    "enabled": true,
                    "targetAllUsers": false,
                    "segments": [
                        5
                    ],
                    "prices": [
                        {
                            "itemId": "regGems150",
                            "priceId": 1
                        }
                    ],
                    "notifications": [
                        {
                            "trigger": "ACTIVATED",
                            "notificationTemplateId": 10
                        }
                    ],
                    "startAt": 1415374185745,
                    "endAt": 1415806185745,
                    "createdAt": 0,
                    "updatedAt": 1415729753294
                }
            ]
        }
    }
    

    Get eligible promotions.

    Service Operation
    "appStore" "ELIGIBLE_PROMOTIONS"

    GetSalesInventory

    NSString *storeId = @"itunes";
    NSString *category = @null;
    NSString *priceInfoCriteria = @null;
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [[_bc appStoreService] getSalesInventory:storeId
                       category:category
              priceInfoCriteria:priceInfoCriteria
                completionBlock:successBlock
           errorCompletionBlock:failureBlock
                       cbObject:nil];
    
    const char *storeId = "itunes";
    const char *category = null;
    const char *priceInfoCriteria = null;
    
    _bc->getAppStore()->getSalesInventory(storeId, category, priceInfoCriteria, this);
    
    string storeId = "itunes";
    string category = null;
    string priceInfoCriteria = null;
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("Success | {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("Failed | {0}  {1}  {2}", status, code, error));
    };
    
    _bc.AppStore.GetSalesInventory(storeId, category, priceInfoCriteria, successCallback, failureCallback);
    
    String storeId = "itunes";
    String category = null;
    String priceInfoCriteria = null;
    this; // implements IServerCallback
    
    _bc.getAppStore().getSalesInventory(storeId, category, priceInfoCriteria, this);
    
    public void serverCallback(ServiceName serviceName, ServiceOperation serviceOperation, JSONObject jsonData)
    {
        System.out.print(String.format("Success | %s", jsonData.toString()));
    }
    public void serverError(ServiceName serviceName, ServiceOperation serviceOperation, int statusCode, int reasonCode, String jsonError)
    {
        System.out.print(String.format("Failed | %d %d %s", statusCode,  reasonCode, jsonError.toString()));
    }
    
    var storeId = "itunes";
    var category = null;
    var priceInfoCriteria = null;
    
    _bc.appStore.getSalesInventory(storeId, category, priceInfoCriteria, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    var storeId = "itunes";
    var category = null;
    var priceInfoCriteria = null;
    var appStoreProxy = bridge.getAppStoreServiceProxy();
    
    var postResult = appStoreProxy.getSalesInventory(storeId, category, priceInfoCriteria);
    if (postResult.status == 200) {
        // Success!
    }
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": {
            "product_inventory": [
                {
                    "currency": {
                        "bar": 50
                    },
                    "description": "Bundle of 50 Bars.",
                    "fbUrl": "https://dev.braincloudservers.com/fbproductservice?gameId=eggies&itemId=barBundle2Imp",
                    "gameId": "eggies",
                    "imageUrl": "http://eggies6waves.braincloudservers.com/s3/eggies-prod/store/bars.png",
                    "itemId": "barBundle2Imp",
                    "priceData": {
                        "ids": [
                            {
                                "appId": "ipad",
                                "itunesId": "com.playbrains.eggiesdevhd2.barBundle2Imp"
                            },
                            {
                                "appId": "iphone",
                                "itunesId": "com.playbrains.eggiesdev2.barBundle2Imp"
                            }
                        ]
                    },
                    "title": "Bars"
                }
            ],
            "server_time": 1395952561266
        }
    }
    

    Method gets the active sales inventory for the passed-in currency type and platform.

    Valid platforms are: - itunes - facebook - appworld - steam - windows - windowsPhone - googlePlay

    Service Operation
    "appStore" "GET_INVENTORY"
    Method Parameters
    Parameter Description
    platform The store platform.
    userCurrency The currency to retrieve the sales inventory for. This is only used for Steam and Facebook stores.

    GetSalesInventoryByCategory

    string platform = "googlePlay";
    string currencyType = "credits";
    string category = "test";
    
    _bc.AppStoreService.GetSalesInventoryByCategory(
        platform,
        currencyType,
        category,
        ApiSuccess, ApiError);
    
    const char * platform = "googlePlay";
    const char * currencyType = "credits";
    const char * category = "test";
    
    _bc->getAppStoreService()->getSalesInventoryByCategory(
        platform, currencyType, category, this);
    
    - (void)getSalesInventoryByCategory:(NSString *)platform
                           userCurrency:(NSString *)userCurrency
                               category:(NSString *)category
                        completionBlock:(BCCompletionBlock)completionBlock
                   errorCompletionBlock:(BCErrorCompletionBlock)errorCompletionBlock
                               cbObject:(BCCallbackObject)cbObject;
    
    public void getSalesInventoryByCategory(
        String in_platform,
        String in_userCurrency,
        String in_category,
        IServerCallback callback)
    
    _bc.appStore.getSalesInventoryByCategory = function(platform, userCurrency, category, callback)
    
    var platform = "itunes";
    var userCurrency = "credits";
    var category = "test";
    
    var appStoreProxy = bridge.getAppStoreServiceProxy();
    var retVal = appStoreProxy.getSalesInventoryByCategory(platform, userCurrency, category);
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": {
            "product_inventory": [
                {
                    "currency": {
                        "bar": 50
                    },
                    "description": "Bundle of 50 Bars.",
                    "fbUrl": "https://dev.braincloudservers.com/fbproductservice?gameId=eggies&itemId=barBundle2Imp",
                    "gameId": "eggies",
                    "imageUrl": "http://eggies6waves.braincloudservers.com/s3/eggies-prod/store/bars.png",
                    "itemId": "barBundle2Imp",
                    "priceData": {
                        "ids": [
                            {
                                "appId": "ipad",
                                "itunesId": "com.playbrains.eggiesdevhd2.barBundle2Imp"
                            },
                            {
                                "appId": "iphone",
                                "itunesId": "com.playbrains.eggiesdev2.barBundle2Imp"
                            }
                        ]
                    },
                    "title": "Bars"
                }
            ],
            "server_time": 1395952561266
        }
    }
    

    Method gets the active sales inventory for the passed-in currency type, platform, and category.

    Valid platforms are: - itunes - facebook - appworld - steam - windows - windowsPhone - googlePlay

    Service Operation
    "appStore" "GET_INVENTORY"
    Method Parameters
    Parameter Description
    platform The store platform.
    userCurrency The currency to retrieve the sales inventory for. This is only used for Steam and Facebook stores.
    category The product category

    StartPurchase

    NSString *storeId = @"itunes";
    NSString *purchaseData = @"{\"itemId\":\"3555\"}";
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [[_bc appStoreService] startPurchase:storeId
                   purchaseData:purchaseData
                completionBlock:successBlock
           errorCompletionBlock:failureBlock
                       cbObject:nil];
    
    const char *storeId = "itunes";
    const char *purchaseData = "{\"itemId\":\"3555\"}";
    
    _bc->getAppStore()->startPurchase(storeId, purchaseData, this);
    
    string storeId = "itunes";
    string purchaseData = "{\"itemId\":\"3555\"}";
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("Success | {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("Failed | {0}  {1}  {2}", status, code, error));
    };
    
    _bc.AppStore.StartPurchase(storeId, purchaseData, successCallback, failureCallback);
    
    String storeId = "itunes";
    String purchaseData = "{\"itemId\":\"3555\"}";
    this; // implements IServerCallback
    
    _bc.getAppStore().startPurchase(storeId, purchaseData, this);
    
    public void serverCallback(ServiceName serviceName, ServiceOperation serviceOperation, JSONObject jsonData)
    {
        System.out.print(String.format("Success | %s", jsonData.toString()));
    }
    public void serverError(ServiceName serviceName, ServiceOperation serviceOperation, int statusCode, int reasonCode, String jsonError)
    {
        System.out.print(String.format("Failed | %d %d %s", statusCode,  reasonCode, jsonError.toString()));
    }
    
    var storeId = "itunes";
    var purchaseData = {
        "itemId": "3555"
    };
    
    _bc.appStore.startPurchase(storeId, purchaseData, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    var storeId = "itunes";
    var purchaseData = {
        "itemId": "3555"
    };
    var appStoreProxy = bridge.getAppStoreServiceProxy();
    
    var postResult = appStoreProxy.startPurchase(storeId, purchaseData);
    if (postResult.status == 200) {
        // Success!
    }
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": {}
    }
    

    Initialize a two-part purchase transaction.

    Service Operation
    "appStore" "START_STEAM_TRANSACTION"
    Method Parameters
    Parameter Description
    language ISO 639-1 language code
    itemId Items to purchase

    VerifyPurchase

    NSString *storeId = @"hghghsgfh";
    NSString *receiptData = @"{\"productId\":\"ugfhffhgj\"}";
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [[_bc appStoreService] verifyPurchase:storeId
                    receiptData:receiptData
                completionBlock:successBlock
           errorCompletionBlock:failureBlock
                       cbObject:nil];
    
    const char *storeId = "hghghsgfh";
    const char *receiptData = "{\"productId\":\"ugfhffhgj\"}";
    
    _bc->getAppStore()->verifyPurchase(storeId, receiptData, this);
    
    string storeId = "hghghsgfh";
    string receiptData = "{\"productId\":\"ugfhffhgj\"}";
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("Success | {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("Failed | {0}  {1}  {2}", status, code, error));
    };
    
    _bc.AppStore.VerifyPurchase(storeId, receiptData, successCallback, failureCallback);
    
    String storeId = "hghghsgfh";
    String receiptData = "{\"productId\":\"ugfhffhgj\"}";
    this; // implements IServerCallback
    
    _bc.getAppStore().verifyPurchase(storeId, receiptData, this);
    
    public void serverCallback(ServiceName serviceName, ServiceOperation serviceOperation, JSONObject jsonData)
    {
        System.out.print(String.format("Success | %s", jsonData.toString()));
    }
    public void serverError(ServiceName serviceName, ServiceOperation serviceOperation, int statusCode, int reasonCode, String jsonError)
    {
        System.out.print(String.format("Failed | %d %d %s", statusCode,  reasonCode, jsonError.toString()));
    }
    
    var storeId = "hghghsgfh";
    var receiptData = {
        "productId": "ugfhffhgj"
    };
    
    _bc.appStore.verifyPurchase(storeId, receiptData, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    var storeId = "hghghsgfh";
    var receiptData = {
        "productId": "ugfhffhgj"
    };
    var appStoreProxy = bridge.getAppStoreServiceProxy();
    
    var postResult = appStoreProxy.verifyPurchase(storeId, receiptData);
    if (postResult.status == 200) {
        // Success!
    }
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": {
            "resultCode": 0,
            "errorMessage":null,
    
            "store": "itunes",
    
            "transactionSummary": {
                "processedCount": 1,
                "unprocessedCount": 0,
                "transactionDetails": [
                    {
                        "transaction_id": "1000000234728140"
                        "original_transaction_id": "1000000234728140",
                        "product_id": "Coins100",
                        "purchase_date_ms": 1473325498000,
                        "purchase_date": "2016-09-08 09:04:58 Etc/GMT",
                        "quantity": 1,
                        "transactionStatus": 0,
                    }
                ],
                "extra": {
                    "appleReceipt": "stringified json receipt data"
                }  
            },
    
            "rewards": {
                "currency": {
                    "coins": 1000
                },
                "parentCurrency": {
                    "awesomeMaster": {
                        "rubies": 2000
                    }
                },
                "peerCurrency": {
                    "peerApp": {
                        "rogerCurrency": 30
                    }
                }          
            },
    
            "currency": {
                "coins": {
                    "balance": 1000,
                    "purchased": 1000,
                    "awarded": 0,
                    "consumed": 0
                 }
            },
    
            "parentCurrency": {
                "awesomeMaster": {
                    "rubies": {
                        "balance": 2000,
                        "purchased": 2000,
                        "awarded": 0,
                        "consumed": 0
                    }
                }
            },
    
            "peerCurrency": {
                "peerApp": {
                    "rogerCurrency": {
                        "balance": 30,
                        "purchased": 30,
                        "awarded": 0,
                        "consumed": 0
                    }
                }
            },
    
            "server_time": 1473325588695
        }
    }
    

    Used to verify a purchase receipt. The contents passed into receiptData are store-specific. On success, the player will be awarded the associated currencies.

    Service Operation
    "appStore" "OP_CASH_IN_RECEIPT"
    Method Parameters
    Parameter Description
    storeId The store type - "itunes", "googlePlay", "facebook" or "windows"
    receiptData A JSON object with data in the format for the specified store
    ReceiptData formats
    Apple AppStore

    Use "itunes" as the storeId.

    iTunes receiptData format: { "receipt": "ENCODED-RECEIPT-DATA" }

    Google Play Store

    Use "googlePlay" as the storeId.

    Google Play receiptData format: { "productId" : "gem_1_wolf", "orderId" : "GPA.3313-2937-0308-63129", "token" : "ENCODED_TOKEN_STRING", "developerPayload" : "STRING_ENCODED_JSON" }

    Facebook

    Use "facebook" as the storeId.

    Facebook receiptData format: { "a": "b" }

    Response fields

    The following fields are included in the json response:

    Field Description
    resultCode the overall status of teh operation
    errorMessage (optional) message describing non-zero result codes
    store the store used for the purchase
    transactionSummary the store-specific response details. Contents vary by store-type.
    rewards the total currencies being rewarded as a result of the purchases(s). Includes subsections by currency scope.
    currency currency balances.
    parentCurrency balances of parent currencies (if any)
    peerCurrency balances of peer currencies (if any)
    server_time utc time on the server (in millis)
    iTunes responses

    Apple receipts will often contain old transactions. The key values of the return to evaluate include:

    Transaction Status codes
    Code Name Description
    0 STATUS_OK Successfully verified, new currencies awarded.
    100 STATUS_FAILED_ALREADY_PROCESSED Already verified and awarded currencies.
    101 STATUS_FAILED_NO_ITUNES_PRODUCT_ID The product id is not configured in iTunes Connect for this app. This is likely a fraud attempt.
    102 STATUS_FAILED_PRODUCT_NOT_FOUND iTunes product id exists, but cannot locate the product in brainCloud Product Inventory. This is likely a configuration error in the brainCloud product - double-check the iTunes price settings for the product.*

    Async Match

    Many mobile games today feature a type of multiplayer game capability known as asynchronous or turn-based gaming. This is where player #1 would take a turn, then player #2 is notified that it is their turn (via push notification). Player #2 would then take their turn and player #1 is then notified it is again their turn and so on until the game is completed (think of playing a game of chess via mail).

    This page describes the design used to facilitate this type of multiplayer game within brainCloud.

    Match Lifecycle

    An Async Match can exist in four states that define where it is in its lifecycle. Certain operations are only supported in specific states.

    The current state is returned in the "status" field of the match data.

    NOT_STARTED

    A match has been created but has not had any turns submitted. A match in this state cannot be completed (status set to COMPLETE).

    PENDING

    The match has had at least one turn submitted.

    COMPLETE

    A match that has been explicitly completed via the CompleteMatch API. A match cannot be completed if its current status is NOT_STARTED.

    EXPIRED

    A match that has been explicitly abandoned via the AbandonMatch API. A match cannot be abandoned if its current status is COMPLETE.

    Data Model

    The following diagram illustrates the data model implemented in brainCloud to support this feature:

    Async Match Data Model

    Match Entity

    The Match entity represents a single asynchronous match between two or more players (for example a single game of chess or tic-tac-toe).

    MatchHistory Entity

    The MatchHistory entity represents the turn-by-turn history of the state related to a particular match.

    Player Entity

    The Player entity represents the actual player. We are simply using the "lastLogin" attribute to identify those Player's that have been pre-created by the AsyncMatchService (by checking if the "lastLogin" field is NULL).

    API Summary

    Match Management
    Turns
    Match Data

    AbandonMatch

    NSString *ownerId = @"internalPlayerId";
    NSString *matchId = @"matchId";
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [[_bc asyncMatchService] abandonMatch:ownerId
                        matchId:matchId
                completionBlock:successBlock
           errorCompletionBlock:failureBlock
                       cbObject:nil];
    
    const char *ownerId = "internalPlayerId";
    const char *matchId = "matchId";
    
    _bc->getAsyncMatch()->abandonMatch(ownerId, matchId, this);
    
    string ownerId = "internalPlayerId";
    string matchId = "matchId";
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("Success | {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("Failed | {0}  {1}  {2}", status, code, error));
    };
    
    _bc.AsyncMatch.AbandonMatch(ownerId, matchId, successCallback, failureCallback);
    
    String ownerId = "internalPlayerId";
    String matchId = "matchId";
    this; // implements IServerCallback
    
    _bc.getAsyncMatch().abandonMatch(ownerId, matchId, this);
    
    public void serverCallback(ServiceName serviceName, ServiceOperation serviceOperation, JSONObject jsonData)
    {
        System.out.print(String.format("Success | %s", jsonData.toString()));
    }
    public void serverError(ServiceName serviceName, ServiceOperation serviceOperation, int statusCode, int reasonCode, String jsonError)
    {
        System.out.print(String.format("Failed | %d %d %s", statusCode,  reasonCode, jsonError.toString()));
    }
    
    var ownerId = "internalPlayerId";
    var matchId = "matchId";
    
    _bc.asyncMatch.abandonMatch(ownerId, matchId, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    var ownerId = "internalPlayerId";
    var matchId = "matchId";
    var asyncMatchProxy = bridge.getAsyncMatchServiceProxy();
    
    var postResult = asyncMatchProxy.abandonMatch(ownerId, matchId);
    if (postResult.status == 200) {
        // Success!
    }
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": null
    }
    

    Marks the given match as abandoned and sets the matchState to EXPIRED.

    Service Operation
    "asyncMatch" "ABANDON"
    Method Parameters
    Parameter Description
    ownerId Match owner identifier
    matchId Match identifier

    CompleteMatch

    NSString *ownerId = @"internalPlayerId";
    NSString *matchId = @"matchId";
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [[_bc asyncMatchService] completeMatch:ownerId
                        matchId:matchId
                completionBlock:successBlock
           errorCompletionBlock:failureBlock
                       cbObject:nil];
    
    const char *ownerId = "internalPlayerId";
    const char *matchId = "matchId";
    
    _bc->getAsyncMatch()->completeMatch(ownerId, matchId, this);
    
    string ownerId = "internalPlayerId";
    string matchId = "matchId";
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("Success | {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("Failed | {0}  {1}  {2}", status, code, error));
    };
    
    _bc.AsyncMatch.CompleteMatch(ownerId, matchId, successCallback, failureCallback);
    
    String ownerId = "internalPlayerId";
    String matchId = "matchId";
    this; // implements IServerCallback
    
    _bc.getAsyncMatch().completeMatch(ownerId, matchId, this);
    
    public void serverCallback(ServiceName serviceName, ServiceOperation serviceOperation, JSONObject jsonData)
    {
        System.out.print(String.format("Success | %s", jsonData.toString()));
    }
    public void serverError(ServiceName serviceName, ServiceOperation serviceOperation, int statusCode, int reasonCode, String jsonError)
    {
        System.out.print(String.format("Failed | %d %d %s", statusCode,  reasonCode, jsonError.toString()));
    }
    
    var ownerId = "internalPlayerId";
    var matchId = "matchId";
    
    _bc.asyncMatch.completeMatch(ownerId, matchId, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    var ownerId = "internalPlayerId";
    var matchId = "matchId";
    var asyncMatchProxy = bridge.getAsyncMatchServiceProxy();
    
    var postResult = asyncMatchProxy.completeMatch(ownerId, matchId);
    if (postResult.status == 200) {
        // Success!
    }
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": null
    }
    

    Marks the given match as complete.

    Service Operation
    "asyncMatch" "COMPLETE"
    Method Parameters
    Parameter Description
    ownerId Match owner identifier
    matchId Match identifier

    CreateMatch

    NSString *jsonOpponentIds = @"[{\"platform\":\"BC\",\"id\":\"profile ID-1\"},{\"platform\":\"FB\",\"id\":\"Facebook ID-1\"},{\"platform\":\"FB\",\"id\":\"Facebook ID-2\"}]";
    NSString *pushNotificationMessage = @"You have been entered into an async-match!";
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [[_bc asyncMatchService] createMatch:jsonOpponentIds
        pushNotificationMessage:pushNotificationMessage
                completionBlock:successBlock
           errorCompletionBlock:failureBlock
                       cbObject:nil];
    
    const char *jsonOpponentIds = "[{\"platform\":\"BC\",\"id\":\"profile ID-1\"},{\"platform\":\"FB\",\"id\":\"Facebook ID-1\"},{\"platform\":\"FB\",\"id\":\"Facebook ID-2\"}]";
    const char *pushNotificationMessage = "You have been entered into an async-match!";
    
    _bc->getAsyncMatch()->createMatch(jsonOpponentIds, pushNotificationMessage, this);
    
    string jsonOpponentIds = "[{\"platform\":\"BC\",\"id\":\"profile ID-1\"},{\"platform\":\"FB\",\"id\":\"Facebook ID-1\"},{\"platform\":\"FB\",\"id\":\"Facebook ID-2\"}]";
    string pushNotificationMessage = "You have been entered into an async-match!";
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("Success | {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("Failed | {0}  {1}  {2}", status, code, error));
    };
    
    _bc.AsyncMatch.CreateMatch(jsonOpponentIds, pushNotificationMessage, successCallback, failureCallback);
    
    String jsonOpponentIds = "[{\"platform\":\"BC\",\"id\":\"profile ID-1\"},{\"platform\":\"FB\",\"id\":\"Facebook ID-1\"},{\"platform\":\"FB\",\"id\":\"Facebook ID-2\"}]";
    String pushNotificationMessage = "You have been entered into an async-match!";
    this; // implements IServerCallback
    
    _bc.getAsyncMatch().createMatch(jsonOpponentIds, pushNotificationMessage, this);
    
    public void serverCallback(ServiceName serviceName, ServiceOperation serviceOperation, JSONObject jsonData)
    {
        System.out.print(String.format("Success | %s", jsonData.toString()));
    }
    public void serverError(ServiceName serviceName, ServiceOperation serviceOperation, int statusCode, int reasonCode, String jsonError)
    {
        System.out.print(String.format("Failed | %d %d %s", statusCode,  reasonCode, jsonError.toString()));
    }
    
    var jsonOpponentIds = [
        {
            "platform": "BC",
            "id": "profile ID-1"
        },
        {
            "platform": "FB",
            "id": "Facebook ID-1"
        },
        {
            "platform": "FB",
            "id": "Facebook ID-2"
        }
    ];
    var pushNotificationMessage = "You have been entered into an async-match!";
    
    _bc.asyncMatch.createMatch(jsonOpponentIds, pushNotificationMessage, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    var jsonOpponentIds = [
        {
            "platform": "BC",
            "id": "profile ID-1"
        },
        {
            "platform": "FB",
            "id": "Facebook ID-1"
        },
        {
            "platform": "FB",
            "id": "Facebook ID-2"
        }
    ];
    var pushNotificationMessage = "You have been entered into an async-match!";
    var asyncMatchProxy = bridge.getAsyncMatchServiceProxy();
    
    var postResult = asyncMatchProxy.createMatch(jsonOpponentIds, pushNotificationMessage);
    if (postResult.status == 200) {
        // Success!
    }
    
    Show Example JSON Return {}
    {
        "status" : 200,
        "data" :
        {
            "gameId": "com.dnadpk.football",
            "ownerId": "0df9f282-183b-4d67-866e-670fb35a2376",
            "matchId": "match1",
            "version": 0,
            "players": [
                {
                    "playerId": "0df9f282-183b-4d67-866e-670fb35a2376",
                    "playerName": "",
                    "pictureUrl": null
                },
                {
                    "playerId": "4693ec75-3a99-4577-aef7-0f41d299339c",
                    "playerName": "Presto1",
                    "pictureUrl": null
                }
            ],
            "status": {
                "status": "NOT_STARTED",
                "currentPlayer": "0df9f282-183b-4d67-866e-670fb35a2376"
            },
            "summary": null,
            "createdAt": 1415641372974,
            "updatedAt": 1415641372974
        }
    }
    

    Creates an instance of an asynchronous match.

    Opponents is a JSON array containing objects with a Platform and player ID. Platforms are identified as:

    An example of this string would be:

    [{ "platform":"BC", "id": "some-braincloud-profile" }, { "platform":"FB", "id": "some-facebook-id" }]

    Service Operation
    "asyncMatch" "CREATE"
    Method Parameters
    Parameter Description
    jsonOpponentIds List of objects identifying the opponent platform and id for this match.
    pushNotificationMessage Optional push notification message to send to the other party. Refer to the Push Notification functions for the syntax required.

    CreateMatchWithInitialTurn

    NSString *jsonOpponentIds = @"[{\"platform\":\"BC\",\"id\":\"profile ID-1\"},{\"platform\":\"FB\",\"id\":\"Facebook ID-1\"}]";
    NSString *jsonMatchState = @"{}";
    NSString *pushNotificationMessage = @"You have been entered into an async-match!";
    NSString *nextPlayer = @"Facebook ID-1";
    NSString *jsonSummary = @"{\"Address\": \"South Africa\"}";
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [[_bc asyncMatchService] createMatchWithInitialTurn:jsonOpponentIds
                 jsonMatchState:jsonMatchState
        pushNotificationMessage:pushNotificationMessage
                     nextPlayer:nextPlayer
                    jsonSummary:jsonSummary
                completionBlock:successBlock
           errorCompletionBlock:failureBlock
                       cbObject:nil];
    
    const char *jsonOpponentIds = "[{\"platform\":\"BC\",\"id\":\"profile ID-1\"},{\"platform\":\"FB\",\"id\":\"Facebook ID-1\"}]";
    const char *jsonMatchState = "{}";
    const char *pushNotificationMessage = "You have been entered into an async-match!";
    const char *nextPlayer = "Facebook ID-1";
    const char *jsonSummary = {
        "Address": "South Africa"
    };
    
    _bc->getAsyncMatch()->createMatchWithInitialTurn(jsonOpponentIds, jsonMatchState, pushNotificationMessage, nextPlayer, jsonSummary, this);
    
    string jsonOpponentIds = "[{\"platform\":\"BC\",\"id\":\"profile ID-1\"},{\"platform\":\"FB\",\"id\":\"Facebook ID-1\"}]";
    string jsonMatchState = "{}";
    string pushNotificationMessage = "You have been entered into an async-match!";
    string nextPlayer = "Facebook ID-1";
    string jsonSummary = {
        "Address": "South Africa"
    };
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("Success | {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("Failed | {0}  {1}  {2}", status, code, error));
    };
    
    _bc.AsyncMatch.CreateMatchWithInitialTurn(jsonOpponentIds, jsonMatchState, pushNotificationMessage, nextPlayer, jsonSummary, successCallback, failureCallback);
    
    String jsonOpponentIds = "[{\"platform\":\"BC\",\"id\":\"profile ID-1\"},{\"platform\":\"FB\",\"id\":\"Facebook ID-1\"}]";
    String jsonMatchState = "{}";
    String pushNotificationMessage = "You have been entered into an async-match!";
    String nextPlayer = "Facebook ID-1";
    String jsonSummary = {
        "Address": "South Africa"
    };
    this; // implements IServerCallback
    
    _bc.getAsyncMatch().createMatchWithInitialTurn(jsonOpponentIds, jsonMatchState, pushNotificationMessage, nextPlayer, jsonSummary, this);
    
    public void serverCallback(ServiceName serviceName, ServiceOperation serviceOperation, JSONObject jsonData)
    {
        System.out.print(String.format("Success | %s", jsonData.toString()));
    }
    public void serverError(ServiceName serviceName, ServiceOperation serviceOperation, int statusCode, int reasonCode, String jsonError)
    {
        System.out.print(String.format("Failed | %d %d %s", statusCode,  reasonCode, jsonError.toString()));
    }
    
    var jsonOpponentIds = [
        {
            "platform": "BC",
            "id": "profile ID-1"
        },
        {
            "platform": "FB",
            "id": "Facebook ID-1"
        }
    ];
    var jsonMatchState = {};
    var pushNotificationMessage = "You have been entered into an async-match!";
    var nextPlayer = "Facebook ID-1";
    var jsonSummary = {
        "Address": "South Africa"
    };
    
    _bc.asyncMatch.createMatchWithInitialTurn(jsonOpponentIds, jsonMatchState, pushNotificationMessage, nextPlayer, jsonSummary, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    var jsonOpponentIds = [
        {
            "platform": "BC",
            "id": "profile ID-1"
        },
        {
            "platform": "FB",
            "id": "Facebook ID-1"
        }
    ];
    var jsonMatchState = {};
    var pushNotificationMessage = "You have been entered into an async-match!";
    var nextPlayer = "Facebook ID-1";
    var jsonSummary = {
        "Address": "South Africa"
    };
    var asyncMatchProxy = bridge.getAsyncMatchServiceProxy();
    
    var postResult = asyncMatchProxy.createMatchWithInitialTurn(jsonOpponentIds, jsonMatchState, pushNotificationMessage, nextPlayer, jsonSummary);
    if (postResult.status == 200) {
        // Success!
    }
    
    Show Example JSON Return {}
    {
        "data" : {
            "createdAt" : 1449737412088,
            "gameId" : "102345",
            "matchId" : "af876cc7-1dd1-4fbe-959d-a9awdsab9a1c",
            "ownerId" : "c76009c3-ea92-41c5-8560-e1dwasc07ce6b",
            "players" : [
                {
                    "pictureUrl" : null,
                    "playerId" : "c76009c3-ea92-41c5-8560-e1dwasc07ce6b",
                    "playerName" : "UserA_CPP_96764398"
                },
                {
                    "pictureUrl" : null,
                    "playerId" : "3bb9dwasdd-9c9a-454f-ae17-9703a66973c8",
                    "playerName" : "UserB_CPP_80148460"
                }
            ],
            "status" : {
                "currentPlayer" : "3bb9dwasdd-9c9a-454f-ae17-9703a66973c8",
                "status" : "PENDING"
            },
            "summary" : {
                "map" : "level01"
            },
            "updatedAt" : 1449737412092,
            "version" : 1
        },
        "status" : 200
    }
    

    Creates an instance of an asynchronous match with an initial turn.

    Opponent IDs is a JSON array containing objects with a Platform and player ID. Platforms are identified as:

    An example of this string would be:

    [{ "platform":"BC", "id": "some-braincloud-profile" }, { "platform":"FB", "id": "some-facebook-id" }]

    Service Operation
    "asyncMatch" "CREATE"
    Method Parameters
    Parameter Description
    jsonOpponentIds List of objects identifying the opponent platform and id for this match.
    jsonMatchState JSON string blob provided by the caller
    pushNotificationMessage Optional push notification message to send to the other party. Refer to the Push Notification functions for the syntax required.
    nextPlayer Optionally, force the next player player to be a specific player
    jsonSummary Optional JSON string defining what the other player will see as a summary of the game when listing their games

    DeleteMatch

    NSString *ownerId = @"internalPlayerId";
    NSString *matchId = @"matchId";
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [[_bc asyncMatchService] deleteMatch:ownerId
                        matchId:matchId
                completionBlock:successBlock
           errorCompletionBlock:failureBlock
                       cbObject:nil];
    
    const char *ownerId = "internalPlayerId";
    const char *matchId = "matchId";
    
    _bc->getAsyncMatch()->deleteMatch(ownerId, matchId, this);
    
    string ownerId = "internalPlayerId";
    string matchId = "matchId";
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("Success | {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("Failed | {0}  {1}  {2}", status, code, error));
    };
    
    _bc.AsyncMatch.DeleteMatch(ownerId, matchId, successCallback, failureCallback);
    
    String ownerId = "internalPlayerId";
    String matchId = "matchId";
    this; // implements IServerCallback
    
    _bc.getAsyncMatch().deleteMatch(ownerId, matchId, this);
    
    public void serverCallback(ServiceName serviceName, ServiceOperation serviceOperation, JSONObject jsonData)
    {
        System.out.print(String.format("Success | %s", jsonData.toString()));
    }
    public void serverError(ServiceName serviceName, ServiceOperation serviceOperation, int statusCode, int reasonCode, String jsonError)
    {
        System.out.print(String.format("Failed | %d %d %s", statusCode,  reasonCode, jsonError.toString()));
    }
    
    var ownerId = "internalPlayerId";
    var matchId = "matchId";
    
    _bc.asyncMatch.deleteMatch(ownerId, matchId, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    var ownerId = "internalPlayerId";
    var matchId = "matchId";
    var asyncMatchProxy = bridge.getAsyncMatchServiceProxy();
    
    var postResult = asyncMatchProxy.deleteMatch(ownerId, matchId);
    if (postResult.status == 200) {
        // Success!
    }
    
    Show Example JSON Return {}
    {
     "status": 200,
     "data": null
    }
    

    Removes the match and match history from the server.

    Service Operation
    "asyncMatch" "DELETE_MATCH"
    Method Parameters
    Parameter Description
    ownerId Match owner identifier
    matchId Match identifier

    FindCompleteMatches

    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [[_bc asyncMatchService] findCompleteMatches:successBlock
           errorCompletionBlock:failureBlock
                       cbObject:nil];
    
    _bc->getAsyncMatch()->findCompleteMatches(this);
    
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("Success | {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("Failed | {0}  {1}  {2}", status, code, error));
    };
    
    _bc.AsyncMatch.FindCompleteMatches(successCallback, failureCallback);
    
    this; // implements IServerCallback
    
    _bc.getAsyncMatch().findCompleteMatches(this);
    
    public void serverCallback(ServiceName serviceName, ServiceOperation serviceOperation, JSONObject jsonData)
    {
        System.out.print(String.format("Success | %s", jsonData.toString()));
    }
    public void serverError(ServiceName serviceName, ServiceOperation serviceOperation, int statusCode, int reasonCode, String jsonError)
    {
        System.out.print(String.format("Failed | %d %d %s", statusCode,  reasonCode, jsonError.toString()));
    }
    
    _bc.asyncMatch.findCompleteMatches(result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    var asyncMatchProxy = bridge.getAsyncMatchServiceProxy();
    
    var postResult = asyncMatchProxy.findCompleteMatches();
    if (postResult.status == 200) {
        // Success!
    }
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": {
            "results": [
                {
                    "gameId": "109999",
                    "ownerId": "9ad4f990-5466-4d00-a334-de834e1ac4ec",
                    "matchId": "877dd25d-ea21-4857-ba2a-2134d0f5ace2",
                    "version": 2,
                    "players": [
                        {
                            "playerId": "9ad4f990-5466-4d00-a334-de834e1ac4ec",
                            "playerName": "",
                            "pictureUrl": null
                        },
                        {
                            "playerId": "963a2079-6e7a-48de-a4f2-8ab16c811975",
                            "playerName": "",
                            "pictureUrl": null
                        }
                    ],
                    "status": {
                        "status": "COMPLETE",
                        "currentPlayer": "963a2079-6e7a-48de-a4f2-8ab16c811975"
                    },
                    "summary": null,
                    "createdAt": 1442586358023,
                    "updatedAt": 1442586374787
                }
            ]
        }
    }
    

    Returns all matches that are in a COMPLETE state for which the player is involved.

    Service Operation
    "asyncMatch" "FIND_MATCHES_COMPLETED"

    FindMatches

    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [[_bc asyncMatchService] findMatches:successBlock
           errorCompletionBlock:failureBlock
                       cbObject:nil];
    
    _bc->getAsyncMatch()->findMatches(this);
    
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("Success | {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("Failed | {0}  {1}  {2}", status, code, error));
    };
    
    _bc.AsyncMatch.FindMatches(successCallback, failureCallback);
    
    this; // implements IServerCallback
    
    _bc.getAsyncMatch().findMatches(this);
    
    public void serverCallback(ServiceName serviceName, ServiceOperation serviceOperation, JSONObject jsonData)
    {
        System.out.print(String.format("Success | %s", jsonData.toString()));
    }
    public void serverError(ServiceName serviceName, ServiceOperation serviceOperation, int statusCode, int reasonCode, String jsonError)
    {
        System.out.print(String.format("Failed | %d %d %s", statusCode,  reasonCode, jsonError.toString()));
    }
    
    _bc.asyncMatch.findMatches(result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    var asyncMatchProxy = bridge.getAsyncMatchServiceProxy();
    
    var postResult = asyncMatchProxy.findMatches();
    if (postResult.status == 200) {
        // Success!
    }
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": {
            "results": [
                {
                    "gameId": "123456",
                    "ownerId": "7630f98e-1236-4ead-88ee-27ce63b2db2c",
                    "matchId": "97c8d087-40d8-45c2-aa2b-6d0d83424ec5",
                    "version": 1,
                    "players": [
                        {
                            "playerId": "7630f98e-13b6-4ead-88ee-27ce63b2db2c",
                            "playerName": "UserA-122217922",
                            "pictureUrl": null
                        },
                        {
                            "playerId": "b28ff14a-364a-40b3-ac4e-d2b23983519c",
                            "playerName": "UserC-338593317",
                            "pictureUrl": null
                        }
                    ],
                    "status": {
                        "status": "PENDING",
                        "currentPlayer": "efab2d0b-90a1-48cf-8678-ae81d7aaed89"
                    },
                    "summary": null,
                    "createdAt": 1442586020180,
                    "updatedAt": 1442586020188
                }
            ]
        }
    }
    

    Returns all matches that are NOT in a COMPLETE state for which the player is involved.

    Service Operation
    "asyncMatch" "FIND_MATCHES"

    ReadMatch

    NSString *ownerId = @"internalPlayerId";
    NSString *matchId = @"matchId";
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [[_bc asyncMatchService] readMatch:ownerId
                        matchId:matchId
                completionBlock:successBlock
           errorCompletionBlock:failureBlock
                       cbObject:nil];
    
    const char *ownerId = "internalPlayerId";
    const char *matchId = "matchId";
    
    _bc->getAsyncMatch()->readMatch(ownerId, matchId, this);
    
    string ownerId = "internalPlayerId";
    string matchId = "matchId";
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("Success | {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("Failed | {0}  {1}  {2}", status, code, error));
    };
    
    _bc.AsyncMatch.ReadMatch(ownerId, matchId, successCallback, failureCallback);
    
    String ownerId = "internalPlayerId";
    String matchId = "matchId";
    this; // implements IServerCallback
    
    _bc.getAsyncMatch().readMatch(ownerId, matchId, this);
    
    public void serverCallback(ServiceName serviceName, ServiceOperation serviceOperation, JSONObject jsonData)
    {
        System.out.print(String.format("Success | %s", jsonData.toString()));
    }
    public void serverError(ServiceName serviceName, ServiceOperation serviceOperation, int statusCode, int reasonCode, String jsonError)
    {
        System.out.print(String.format("Failed | %d %d %s", statusCode,  reasonCode, jsonError.toString()));
    }
    
    var ownerId = "internalPlayerId";
    var matchId = "matchId";
    
    _bc.asyncMatch.readMatch(ownerId, matchId, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    var ownerId = "internalPlayerId";
    var matchId = "matchId";
    var asyncMatchProxy = bridge.getAsyncMatchServiceProxy();
    
    var postResult = asyncMatchProxy.readMatch(ownerId, matchId);
    if (postResult.status == 200) {
        // Success!
    }
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": {
            "gameId": "11004",
            "ownerId": "35e8698f-b14d-48ae-a37c-4b2962308b8d",
            "matchId": "cfa752d6-d408-4671-9603-b22bf55d5379",
            "version": 1,
            "players": [{
                "playerId": "35e8698f-b14d-48ae-a37c-4b2962308b8d",
                "playerName": "",
                "pictureUrl": null
            }, {
                "playerId": "e84c16ea-bd62-4307-83f9-d32f8ac18bca",
                "playerName": "",
                "pictureUrl": null
            }],
            "status": {
                "status": "PENDING",
                "currentPlayer": "e84c16ea-bd62-4307-83f9-d32f8ac18bca"
            },
            "summary": null,
            "statistics": {},
            "matchState": {
                "testKey": "testValue"
            },
            "createdAt": 1472293357985,
            "updatedAt": 1472293357996
        }
    }
    

    Returns the current state of the given match.

    Service Operation
    "asyncMatch" "READ_MATCH"
    Method Parameters
    Parameter Description
    ownerId Match owner identifier
    matchId Match identifier

    ReadMatchHistory

    NSString *ownerId = @"internalPlayerId";
    NSString *matchId = @"matchId";
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [[_bc asyncMatchService] readMatchHistory:ownerId
                        matchId:matchId
                completionBlock:successBlock
           errorCompletionBlock:failureBlock
                       cbObject:nil];
    
    const char *ownerId = "internalPlayerId";
    const char *matchId = "matchId";
    
    _bc->getAsyncMatch()->readMatchHistory(ownerId, matchId, this);
    
    string ownerId = "internalPlayerId";
    string matchId = "matchId";
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("Success | {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("Failed | {0}  {1}  {2}", status, code, error));
    };
    
    _bc.AsyncMatch.ReadMatchHistory(ownerId, matchId, successCallback, failureCallback);
    
    String ownerId = "internalPlayerId";
    String matchId = "matchId";
    this; // implements IServerCallback
    
    _bc.getAsyncMatch().readMatchHistory(ownerId, matchId, this);
    
    public void serverCallback(ServiceName serviceName, ServiceOperation serviceOperation, JSONObject jsonData)
    {
        System.out.print(String.format("Success | %s", jsonData.toString()));
    }
    public void serverError(ServiceName serviceName, ServiceOperation serviceOperation, int statusCode, int reasonCode, String jsonError)
    {
        System.out.print(String.format("Failed | %d %d %s", statusCode,  reasonCode, jsonError.toString()));
    }
    
    var ownerId = "internalPlayerId";
    var matchId = "matchId";
    
    _bc.asyncMatch.readMatchHistory(ownerId, matchId, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    var ownerId = "internalPlayerId";
    var matchId = "matchId";
    var asyncMatchProxy = bridge.getAsyncMatchServiceProxy();
    
    var postResult = asyncMatchProxy.readMatchHistory(ownerId, matchId);
    if (postResult.status == 200) {
        // Success!
    }
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": {
            "gameId": "14577",
            "ownerId": "2bd32bc6-c2ec-4916-a1a8-02b7a38540ad",
            "matchId": "1aac24b2-7976-4fd7-b7c6-44d32e6d26a4",
            "turns": [
                {
                    "playerId": "2bd32bc6-c2ec-4916-a1a8-02b7a38540ad",
                    "matchState": {
                        "color": "red"
                    },
                    "createdAt": 1442507319697
                },
                {
                    "playerId": "11c9324d-9ed1-416d-b124-5228c1efafac",
                    "matchState": {},
                    "createdAt": 1442507703667
                }
            ]
        }
    }
    

    Returns the match history of the given match.

    Service Operation
    "asyncMatch" "READ_MATCH_HISTORY"
    Method Parameters
    Parameter Description
    ownerId Match owner identifier
    matchId Match identifier

    SubmitTurn

    NSString *ownerId = @"internalPlayerId";
    NSString *matchId = @"matchId";
    NSString *jsonMatchState = @"{}";
    NSString *pushNotificationMessage = @"You have been entered into an async-match!";
    NSString *nextPlayer = @"player2Id";
    NSString *jsonSummary = @"{\"Address\":\"South Africa\"}";
    NSString *jsonStatistics = @"{\"statsName\":\"statValue\"}";
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [[_bc asyncMatchService] submitTurn:ownerId
                        matchId:matchId
                        version:version
                 jsonMatchState:jsonMatchState
        pushNotificationMessage:pushNotificationMessage
                     nextPlayer:nextPlayer
                    jsonSummary:jsonSummary
                 jsonStatistics:jsonStatistics
                completionBlock:successBlock
           errorCompletionBlock:failureBlock
                       cbObject:nil];
    
    const char *ownerId = "internalPlayerId";
    const char *matchId = "matchId";
    const char *jsonMatchState = "{}";
    const char *pushNotificationMessage = "You have been entered into an async-match!";
    const char *nextPlayer = "player2Id";
    const char *jsonSummary = "{\"Address\":\"South Africa\"}";
    const char *jsonStatistics = "{\"statsName\":\"statValue\"}";
    
    _bc->getAsyncMatch()->submitTurn(ownerId, matchId, version, jsonMatchState, pushNotificationMessage, nextPlayer, jsonSummary, jsonStatistics, this);
    
    string ownerId = "internalPlayerId";
    string matchId = "matchId";
    string jsonMatchState = "{}";
    string pushNotificationMessage = "You have been entered into an async-match!";
    string nextPlayer = "player2Id";
    string jsonSummary = "{\"Address\":\"South Africa\"}";
    string jsonStatistics = "{\"statsName\":\"statValue\"}";
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("Success | {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("Failed | {0}  {1}  {2}", status, code, error));
    };
    
    _bc.AsyncMatch.SubmitTurn(ownerId, matchId, version, jsonMatchState, pushNotificationMessage, nextPlayer, jsonSummary, jsonStatistics, successCallback, failureCallback);
    
    String ownerId = "internalPlayerId";
    String matchId = "matchId";
    String jsonMatchState = "{}";
    String pushNotificationMessage = "You have been entered into an async-match!";
    String nextPlayer = "player2Id";
    String jsonSummary = "{\"Address\":\"South Africa\"}";
    String jsonStatistics = "{\"statsName\":\"statValue\"}";
    this; // implements IServerCallback
    
    _bc.getAsyncMatch().submitTurn(ownerId, matchId, version, jsonMatchState, pushNotificationMessage, nextPlayer, jsonSummary, jsonStatistics, this);
    
    public void serverCallback(ServiceName serviceName, ServiceOperation serviceOperation, JSONObject jsonData)
    {
        System.out.print(String.format("Success | %s", jsonData.toString()));
    }
    public void serverError(ServiceName serviceName, ServiceOperation serviceOperation, int statusCode, int reasonCode, String jsonError)
    {
        System.out.print(String.format("Failed | %d %d %s", statusCode,  reasonCode, jsonError.toString()));
    }
    
    var ownerId = "internalPlayerId";
    var matchId = "matchId";
    var jsonMatchState = {};
    var pushNotificationMessage = "You have been entered into an async-match!";
    var nextPlayer = "player2Id";
    var jsonSummary = {
        "Address": "South Africa"
    };
    var jsonStatistics = {
        "statsName": "statValue"
    };
    
    _bc.asyncMatch.submitTurn(ownerId, matchId, version, jsonMatchState, pushNotificationMessage, nextPlayer, jsonSummary, jsonStatistics, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    var ownerId = "internalPlayerId";
    var matchId = "matchId";
    var jsonMatchState = {};
    var pushNotificationMessage = "You have been entered into an async-match!";
    var nextPlayer = "player2Id";
    var jsonSummary = {
        "Address": "South Africa"
    };
    var jsonStatistics = {
        "statsName": "statValue"
    };
    var asyncMatchProxy = bridge.getAsyncMatchServiceProxy();
    
    var postResult = asyncMatchProxy.submitTurn(ownerId, matchId, version, jsonMatchState, pushNotificationMessage, nextPlayer, jsonSummary, jsonStatistics);
    if (postResult.status == 200) {
        // Success!
    }
    
    Show Example JSON Return {}
    {
        "data" : {
            "createdAt" : 1449737412088,
            "gameId" : "102345",
            "matchId" : "af876cc7-1dd1-4fbe-959d-a9awdsab9a1c",
            "ownerId" : "c76009c3-ea92-41c5-8560-e1dwasc07ce6b",
            "players" : [
                {
                    "pictureUrl" : null,
                    "playerId" : "c76009c3-ea92-41c5-8560-e1dwasc07ce6b",
                    "playerName" : "UserA_CPP_96764398"
                },
                {
                    "pictureUrl" : null,
                    "playerId" : "3bb9dwasdd-9c9a-454f-ae17-9703a66973c8",
                    "playerName" : "UserB_CPP_80148460"
                }
            ],
            "status" : {
                "currentPlayer" : "3bb9dwasdd-9c9a-454f-ae17-9703a66973c8",
                "status" : "PENDING"
            },
            "summary" : {
                "map" : "level01"
            },
            "updatedAt" : 1449737412092,
            "version" : 1
        },
        "status" : 200
    }
    

    Submits a turn for the given match.

    Service Operation
    "asyncMatch" "SUBMIT_TURN"
    Method Parameters
    Parameter Description
    ownerId Match owner identifier
    matchId Match identifier
    version Game state version to ensure turns are submitted once and in order
    jsonMatchState JSON string blob provided by the caller
    pushNotificationMessage Optional push notification message to send to the other party. Refer to the Push Notification functions for the syntax required.
    nextPlayer Optionally, force the next player player to be a specific player
    jsonSummary Optional JSON string defining what the other player will see as a summary of the game when listing their games
    jsonStatistics Optional JSON string blob provided by the caller

    UpdateMatchSummaryData

    NSString *ownerId = @"internalPlayerId";
    NSString *matchId = @"matchId";
    NSString *jsonSummary = @"{\"Address\":\"North America\"}";
    BCCompletionBlock successBlock;      // define callback
    BCErrorCompletionBlock failureBlock; // define callback
    
    [[_bc asyncMatchService] updateMatchSummaryData:ownerId
                        matchId:matchId
                        version:version
                    jsonSummary:jsonSummary
                completionBlock:successBlock
           errorCompletionBlock:failureBlock
                       cbObject:nil];
    
    const char *ownerId = "internalPlayerId";
    const char *matchId = "matchId";
    const char *jsonSummary = "{\"Address\":\"North America\"}";
    
    _bc->getAsyncMatch()->updateMatchSummaryData(ownerId, matchId, version, jsonSummary, this);
    
    string ownerId = "internalPlayerId";
    string matchId = "matchId";
    string jsonSummary = "{\"Address\":\"North America\"}";
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Debug.Log(string.Format("Success | {0}", response));
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("Failed | {0}  {1}  {2}", status, code, error));
    };
    
    _bc.AsyncMatch.UpdateMatchSummaryData(ownerId, matchId, version, jsonSummary, successCallback, failureCallback);
    
    String ownerId = "internalPlayerId";
    String matchId = "matchId";
    String jsonSummary = "{\"Address\":\"North America\"}";
    this; // implements IServerCallback
    
    _bc.getAsyncMatch().updateMatchSummaryData(ownerId, matchId, version, jsonSummary, this);
    
    public void serverCallback(ServiceName serviceName, ServiceOperation serviceOperation, JSONObject jsonData)
    {
        System.out.print(String.format("Success | %s", jsonData.toString()));
    }
    public void serverError(ServiceName serviceName, ServiceOperation serviceOperation, int statusCode, int reasonCode, String jsonError)
    {
        System.out.print(String.format("Failed | %d %d %s", statusCode,  reasonCode, jsonError.toString()));
    }
    
    var ownerId = "internalPlayerId";
    var matchId = "matchId";
    var jsonSummary = {
        "Address": "North America"
    };
    
    _bc.asyncMatch.updateMatchSummaryData(ownerId, matchId, version, jsonSummary, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    var ownerId = "internalPlayerId";
    var matchId = "matchId";
    var jsonSummary = {
        "Address": "North America"
    };
    var asyncMatchProxy = bridge.getAsyncMatchServiceProxy();
    
    var postResult = asyncMatchProxy.updateMatchSummaryData(ownerId, matchId, version, jsonSummary);
    if (postResult.status == 200) {
        // Success!
    }
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": {
            "gameId": "145677",
            "ownerId": "2bd723c6-c2ec-4946-a1a8-02b7a38540ad",
            "matchId": "1aac24b2-7976-4fd7-b7c6-44d7ae6d26a4",
            "version": 2,
            "players": [
                {
                    "playerId": "2bd723c6-c2ec-4946-a1a8-02b7a38540ad",
                    "playerName": "UserA",
                    "pictureUrl": null
                },
                {
                    "playerId": "11c2dd4d-9ed1-416d-bd04-5228c1efafac",
                    "playerName": "UserB",
                    "pictureUrl": null
                }
            ],
            "status": {
                "status": "PENDING",
                "currentPlayer": "11c2dd4d-9ed1-416d-bd04-5228c1efafac"
            },
            "summary": {
                "resources": 2564
            },
            "createdAt": 1442507219609,
            "updatedAt": 1442507550372
        }
    }
    

    Allows the current player (only) to update Summary data without having to submit a whole turn.

    Service Operation
    "asyncMatch" "UPDATE_SUMMARY"
    Method Parameters
    Parameter Description
    ownerId Match owner identifier
    matchId Match identifier
    version Game state version to ensure turns are submitted once and in order
    jsonSummary JSON string provided by the caller that other players will see as a summary of the game when listing their games

    Chat

    Chat is a new service that enables real-time communication between end-users. It is available to apps that have brainCloud RTT enabled.

    Key concepts

    Chat message format { "chId": "<channel id>", "msgId": "<guid>", "date": 1530069895070, "ver": 1, "from": { "id": "<profileId>", "name": "<name>", "pic": "<pictureUrl>" }, "content": { "text": "simple message", "rich": {} } }

    Chat message fields

    Field Description
    chId The channel id
    msgId The chat message id (used for editing / deleting posted messages)
    date The time the message was posted (in utc millis)
    ver The version of the message
    from Information about who the chat message is from. Includes name and picture url if available
    content The content of the chat message. Contents are up to the developer - but for visibility in tools, should have a text field for plain-text message content

    Channel Types

    brainCloud currently supports two types of channels:

    Channel Type Membership Creation Description
    global All users of the app Via portal All users of an app can access global channels. By default, an app can have up to 10 channels. Contact us with your use case for more.
    group All members of a Group Auto A channel is automatically created for each group in the system. Any group member can access it.

    Pro-tip - if you are interested in one-to-one chat, see our Messaging api...

    API Summary

    Channel lookup and management
    Retrieving chat messages
    Posting chat messages
    Updating chat messages
    System chat API (cloud-code only)

    These API calls bypass channel membership / message ownership checks - and allow you to post messages from the system (i.e. app) instead of from another end-user:

    ChannelConnect

    const char* channelId = "55555:gl:bcDev";
    int maxReturn = 25;
    this; // implements IServerCallback
    
    _bc->getChat()->channelConnect(channelId, maxReturn);
    
    //Step 1:   Start an RTT connection by calling EnableRTT
    //          http://getbraincloud.com/apidocs/apiref/#capi-client-enablertt
    //Step 2:   Register a chat callback
    RTTCallback rttCallback = response =>
    {
       Debug.Log(response);
    };
    _bc.RegisterRTTChatCallback(rttCallback);
    
    //Step 3:   Now, you can call ChannelConnect
    
    string channelId = "22817:gl:CHAT_TRADE"; // APP_ID:CHANNEL_TYPE:CHANNEL_ID
    int maxReturn = 25;
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Dictionary<string, object> jsonMessage = (Dictionary<string, object>)JsonFx.Json.JsonReader.Deserialize(response);
        Dictionary<string, object> jsonData = (Dictionary<string, object>)jsonMessage["data"];
        var messages = (Dictionary<string, object>[]) jsonData["messages"];
    
        foreach (Dictionary<string, object> message in messages)
        {
            var content = (Dictionary<string, object>)message["content"];
            var item = (Dictionary<string, object>)content["SELL_ITEM"];
    
            string itemType = item["ITEM_TYPE"].ToString();
            string itemId = item["ITEM_ID"].ToString();
            string price = item["PRICE"].ToString();
            string currency = item["CURRENCY"].ToString();
            string logMessage = string.Join(" | ", new[] {itemType, itemId, price, currency});
            Debug.Log(logMessage);  // COUCH | d05a5b9d-374e-41e2-a498-c7387bf15c76 | 105 | GOLDCOINS
        }
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("[ChannelConnect Failed] {0}  {1}  {2}", status, code, error));
    };
    
    _bc.ChatService.ChannelConnect(channelId, maxReturn, successCallback, failureCallback);
    
    String channelId = "22817:gl:CHAT_TRADE"; // APP_ID:CHANNEL_TYPE:CHANNEL_ID
    int maxReturn = 25;
    this; // implements IServerCallback
    
    _bc.getChatService().channelConnect(channelId, maxReturn, this);
    
    public void serverCallback(ServiceName serviceName, ServiceOperation serviceOperation, JSONObject jsonData)
    {
        System.out.print(String.format("Success | %s", jsonData.toString()));
    }
    public void serverError(ServiceName serviceName, ServiceOperation serviceOperation, int statusCode, int reasonCode, String jsonError)
    {
        System.out.print(String.format("Failed | %d %d %s", statusCode,  reasonCode, jsonError.toString()));
    }
    
    Coming soon!
    
    var channelId = "22817:gl:CHAT_TRADE";
    var maxReturn = 25;
    
    _bc.chat.channelConnect(channelId, maxReturn, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    var chatProxy = bridge.getChatServiceProxy();
    
    var idResult = chatProxy.getChannelId( 'gl', 'bitChat' );
    if ( idResult.status == 200 ) {
    
        var channelId = idResult.data.channelId;
    
        connectResult = chatProxy.channelConnect(channelId, 25);
    } 
    
    Show Example JSON Return {}
    {
        "data": {
            "messages": [{
                "date": 1530649082684,
                "ver": 1,
                "msgId": "783692330334210",
                "from": {
                    "id": "a7b7de02-8432-4547-8c40-9af94537fce0",
                    "name": "RedBomber",
                    "pic": null
                },
                "chId": "22817:gl:CHAT_TRADE",
                "content": {
                    "text": "Looking to sell a couch for 105 gold coins.",
                    "rich": {
                        "SELL_ITEM": {
                            "ITEM_TYPE": "COUCH",
                            "ITEM_ID": "d05a5b9d-374e-41e2-a498-c7387bf15c76",
                            "PRICE": "105",
                            "CURRENCY": "GOLDCOINS"
                        }
                    }
                }
            }, 
            {
                "date": 1530650080029,
                "ver": 1,
                "msgId": "783692840974851",
                "from": {
                    "id": "805cc012-0bf1-40a0-9716-b896d8f4c424",
                    "name": "Chantel",
                    "pic": null
                },
                "chId": "22817:gl:CHAT_TRADE",
                "content": {
                    "text": "For that couch, how about 25 gems instead?"
                }
            }, 
            {
                "date": 1530650218944,
                "ver": 1,
                "msgId": "783692912099332",
                "from": {
                    "id": "a7b7de02-8432-4547-8c40-9af94537fce0",
                    "name": "RedBomber",
                    "pic": null
                },
                "chId": "22817:gl:CHAT_TRADE",
                "content": {
                    "text": "Sold!"
                }
            }]
        },
        "status": 200
    }
    

    Registers a handler for incoming events from the specified channelId. Also returns a list of that channel's recent messages (from history).

    Service Operation
    "chat" "CHANNEL_CONNECT"
    Method Parameters
    Parameter Description
    channelId The id of the channel to connect to.
    maxReturn The maximum number of recent messages to return from history.
    Error returns
    Code Name Description
    40346 CHAT_INVALID_CHANNEL_ID The channel id provided is invalid.
    40601 RTT_NOT_ENABLED RTT must be enabled for this feature

    ChannelDisconnect

    const char* channelId = "55555:gl:bcDev";
    this; // implements IServerCallback
    
    _bc->getChat()->channelDisconnect(channelId);
    
    //Step 1:   Start an RTT connection by calling EnableRTT
    //          http://getbraincloud.com/apidocs/apiref/#capi-client-enablertt
    //Step 2:   Now, you can call ChannelDisconnect
    
    string channelId = "22817:gl:CHAT_TRADE"; // APP_ID:CHANNEL_TYPE:CHANNEL_ID
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Dictionary<string, object> jsonMessage = (Dictionary<string, object>)JsonFx.Json.JsonReader.Deserialize(response);
        var status = jsonMessage["status"].ToString();
    
        string logMessage = string.Join(" | ", new [] {status});
        Debug.Log(logMessage); // 200
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("[ChannelDisconnect Failed] {0}  {1}  {2}", status, code, error));
    };
    
    _bc.ChatService.ChannelDisconnect(channelId, successCallback, failureCallback);
    
    String channelId = "22817:gl:CHAT_TRADE"; // APP_ID:CHANNEL_TYPE:CHANNEL_ID
    this; // implements IServerCallback
    
    _bc.getChatService().channelDisconnect(channelId, this);
    
    public void serverCallback(ServiceName serviceName, ServiceOperation serviceOperation, JSONObject jsonData)
    {
        System.out.print(String.format("Success | %s", jsonData.toString()));
    }
    public void serverError(ServiceName serviceName, ServiceOperation serviceOperation, int statusCode, int reasonCode, String jsonError)
    {
        System.out.print(String.format("Failed | %d %d %s", statusCode,  reasonCode, jsonError.toString()));
    }
    
    Coming soon!
    
    var channelId = "22817:gl:CHAT_TRADE";
    
    _bc.chat.channelDisconnect(channelId, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    var chatProxy = bridge.getChatServiceProxy();
    chatProxy.channelDisconnect(channelId);
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": {}
    }
    

    Disconnects from the specified channel, unregistering the handler.

    Service Operation
    "chat" "CHANNEL_DISCONNECT"
    Method Parameters
    Parameter Description
    channelId The id of the channel to connect to.
    Error returns
    Code Name Description
    40346 CHAT_INVALID_CHANNEL_ID The channel id provided is invalid.
    40601 RTT_NOT_ENABLED RTT must be enabled for this feature

    DeleteChatMessage

    const char* channelId = "55555:gl:bcDev";
    const char* msgId = "123456789";
    int version = -1;
    this; // implements IServerCallback
    
    _bc->getChat()->deleteChatMessage(channelId, msgId, version);
    
    //Step 1:   Initialize the brainCloud Wrapper and Authenticate the user 
    //          http://getbraincloud.com/apidocs/apiref/#wrapper
    //Step 2:   Have a msgId from a chat message to delete
    //Step 3:   Now, you can call DeleteChatMessage
    
    string channelId = "22817:gl:CHAT_TRADE"; // APP_ID:CHANNEL_TYPE:CHANNEL_ID
    string msgId = "784130333859899";
    int version = -1;
    SuccessCallback successCallback = (response, cbObject) =>
    {
        var jsonMessage = (Dictionary<string, object>)JsonFx.Json.JsonReader.Deserialize(response);
        Dictionary<string, object> jsonData = (Dictionary<string, object>)jsonMessage["data"];
        string deleted = jsonData["deleted"].ToString();
    
        string logMessage = string.Join(" | ", new [] {deleted});
        Debug.Log(logMessage); // 1
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("[DeleteChatMessage Failed] {0}  {1}  {2}", status, code, error));
    };
    
    _bc.ChatService.DeleteChatMessage(channelId, msgId, version, successCallback, failureCallback);
    
    String channelId = "22817:gl:CHAT_TRADE"; // APP_ID:CHANNEL_TYPE:CHANNEL_ID
    String msgId = "784130333859899";
    int version = -1;
    this; // implements IServerCallback
    
    _bc.getChatService().deleteChatMessage(channelId, msgId, version, this);
    
    public void serverCallback(ServiceName serviceName, ServiceOperation serviceOperation, JSONObject jsonData)
    {
        System.out.print(String.format("Success | %s", jsonData.toString()));
    }
    public void serverError(ServiceName serviceName, ServiceOperation serviceOperation, int statusCode, int reasonCode, String jsonError)
    {
        System.out.print(String.format("Failed | %d %d %s", statusCode,  reasonCode, jsonError.toString()));
    }
    
    Coming soon!
    
    var channelId = "22817:gl:CHAT_TRADE";
    var msgId = "784130333859899";
    var version = -1;
    
    _bc.chat.channelDisconnect(channelId, msgId, version, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    var chatProxy = bridge.getChatServiceProxy();
    var result = chatProxy.deleteChatMessage( channelId, msgId, ver );
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": {
            "deleted": 1
        }
    }
    

    Delete the specified chat message. Message must have been from this user. Version must match (or pass -1 to bypass version enforcement).

    Returns the number of messages that were deleted. Since the history rolls over, it is possible that the message had already expired before the delete attempt - in that case, the value of the deleted field will be 0.

    Service Operation
    "chat" "DELETE_CHAT_MESSAGE"
    Method Parameters
    Parameter Description
    channelId The channel of the message
    msgId The message id
    version The version of the message. Pass it -1 to bypass version checking.
    Error returns
    Code Name Description
    40346 CHAT_INVALID_CHANNEL_ID The channel id provided is invalid.
    40601 RTT_NOT_ENABLED RTT must be enabled for this feature

    GetChannelId

    const char* channelType = "gl";
    const char* channelSubId = "myChatRoom";
    this; // implements IServerCallback
    
    _bc->getChat()->getChannelId(channelType, channelSubId);
    
    //Step 1:   Initialize the brainCloud Wrapper and Authenticate the user 
    //          http://getbraincloud.com/apidocs/apiref/#wrapper
    //Step 2:   Now, you can call GetChannelId
    
    string channelType = "gl";
    string channelSubId = "CHAT_TRADE";
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Dictionary<string, object> jsonMessage = (Dictionary<string, object>)JsonFx.Json.JsonReader.Deserialize(response);
        Dictionary<string, object> jsonData = (Dictionary<string, object>)jsonMessage["data"];
    
        var channelId = jsonData["channelId"].ToString();
    
        string logMessage = string.Join(" | ", new [] {channelId});
        Debug.Log(logMessage); // 22817:gl:CHAT_TRADE
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("[GetChannelId Failed] {0}  {1}  {2}", status, code, error));
    };
    _bc.ChatService.GetChannelId(channelType, channelSubId, successCallback, failureCallback);
    
    String channelType = "gl";
    String channelSubId = "CHAT_TRADE";
    this; // implements IServerCallback
    
    _bc.getChatService().getChannelId(channelType, channelSubId, this);
    
    public void serverCallback(ServiceName serviceName, ServiceOperation serviceOperation, JSONObject jsonData)
    {
        System.out.print(String.format("Success | %s", jsonData.toString()));
    }
    public void serverError(ServiceName serviceName, ServiceOperation serviceOperation, int statusCode, int reasonCode, String jsonError)
    {
        System.out.print(String.format("Failed | %d %d %s", statusCode,  reasonCode, jsonError.toString()));
    }
    
    Coming soon!
    
    var channelType = "gl";
    var channelSubId = "CHAT_TRADE";
    
    _bc.chat.getChannelId(channelType, channelSubId, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    var chatProxy = bridge.getChatServiceProxy();
    var idResult = proxy.getChannelId( 'gl', 'bcChat');
    if (idResult.status == 200 ) {
        channelId = idResult.data.channelId;
    }
    
    Show Example JSON Return {}
    {
        "status": 200,
        "data": {
            "channelId": "22817:gl:CHAT_TRADE"
        }
    }
    

    Retrieves a channel id given the specified lookup parameters.

    Service Operation
    "chat" "GET_CHANNEL_ID"
    Method Parameters
    Parameter Description
    channelType The channel type - 'gl' for global, 'gr' for groups
    channelSubId The type-specific sub id
    Error returns
    Code Name Description
    40601 RTT_NOT_ENABLED RTT must be enabled for this feature
    40603 CHAT_UNRECOGNIZED_CHANNEL The sub id for the channel type is not recognized

    GetChannelInfo

    const char* channelId = "55555:gl:bcDev";
    this; // implements IServerCallback
    
    _bc->getChat()->getChannelInfo(channelId);
    
    //Step 1:   Initialize the brainCloud Wrapper and Authenticate the user 
    //          http://getbraincloud.com/apidocs/apiref/#wrapper
    //Step 2:   Now, you can call GetChannelInfo
    
    string channelId = "22817:gl:CHAT_TRADE"; // APP_ID:CHANNEL_TYPE:CHANNEL_ID
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Dictionary<string, object> jsonMessage = (Dictionary<string, object>)JsonFx.Json.JsonReader.Deserialize(response);
        Dictionary<string, object> jsonData = (Dictionary<string, object>)jsonMessage["data"];
        var name = jsonData["name"].ToString();
        var desc = jsonData["desc"].ToString();
    
        string logMessage = string.Join(" | ", new [] {name, desc});
        Debug.Log(logMessage); // Trade Chat | Trade items here.
    };
    FailureCallback failureCallback = (status, code, error, cbObject) =>
    {
        Debug.Log(string.Format("[GetChannelInfo Failed] {0}  {1}  {2}", status, code, error));
    };
    _bc.ChatService.GetChannelInfo(channelId, successCallback, failureCallback);
    
    String channelType = "gl";
    String channelSubId = "CHAT_TRADE";
    this; // implements IServerCallback
    
    _bc.getChatService().getChannelInfo(channelType, channelSubId, this);
    
    public void serverCallback(ServiceName serviceName, ServiceOperation serviceOperation, JSONObject jsonData)
    {
        System.out.print(String.format("Success | %s", jsonData.toString()));
    }
    public void serverError(ServiceName serviceName, ServiceOperation serviceOperation, int statusCode, int reasonCode, String jsonError)
    {
        System.out.print(String.format("Failed | %d %d %s", statusCode,  reasonCode, jsonError.toString()));
    }
    
    Coming soon!
    
    var channelType = "gl";
    var channelSubId = "CHAT_TRADE";
    
    _bc.chat.getChannelInfo(channelType, channelSubId, result =>
    {
        var status = result.status;
        console.log(status + " : " + JSON.stringify(result, null, 2));
    });
    
    var chatProxy = bridge.getChatServiceProxy();
    var infoResult = chatProxy.getChannelInfo(channelId);
    
    Show Example JSON Return {}
    {
        "data": {
            "id": "22817:gl:CHAT_TRADE",
            "type": "gl",
            "code": "CHAT_TRADE",
            "name": "Trade Chat",
            "desc": "Trade items here.",
            "stats": {
                "messageCount": 25
            }
        },
        "status": 200
    }
    

    Returns description info and activity stats for the specified channel. Note that numMembers, numListeners and listeners are only returned for non-global groups. Only callable by members of the channel.

    Service Operation
    "chat" "GET_CHANNEL_INFO"
    Method Parameters
    Parameter Description
    channelId The id of the channel
    Error returns
    Code Name Description
    40346 CHAT_INVALID_CHANNEL_ID The channel id provided is invalid.
    40601 RTT_NOT_ENABLED RTT must be enabled for this feature

    GetChatMessage

    const char* channelId = "55555:gl:bcDev";
    const char* msgId = "123456789";
    this; // implements IServerCallback
    
    _bc->getChat()->getChatMessage(channelId, msgId);
    
    //Step 1:   Initialize the brainCloud Wrapper and Authenticate the user 
    //          http://getbraincloud.com/apidocs/apiref/#wrapper
    //Step 2:   Now, you can call GetChatMessage
    
    string channelId = "22817:gl:CHAT_GROUPFINDER"; // APP_ID:CHANNEL_TYPE:CHANNEL_ID
    string msgId = "783820066133040";
    SuccessCallback successCallback = (response, cbObject) =>
    {
        Dictionary<string, object> jsonMessage = (Dictionary<string, object>)JsonFx.Json.JsonReader.Deserialize(response);
        Dictionary<string, object> jsonData = (Dictionary<string, object>)jsonMessage["data"];
    
        var date = jsonData["date"].ToString();
        var name = ((Dictionary<string, object>)jsonData["from"])["name"].ToString();
        var text = ((Dictionary<string, object>)jsonData["content"])["text"].