Bitmoji Kit

Bitmoji Kit brings a native Bitmoji experience into your app. Users can access their Bitmoji sticker library in a tap to make messages more fun, more expressive, and truly personal.

Users must be logged into Snapchat to use Bitmoji Kit’s features in your app.

Please ensure your app follows our Bitmoji Kit Integration Checklist and Bitmoji Brand Guidelines.

iOS

Bitmoji Kit iOS gives you access to two Bitmoji features, the avatar icon and sticker picker. The avatar icon gives users a familiar visual identity within your app. The sticker picker lets users browse, search, and send Bitmojis.

Requirements

  • Xcode version 9.0+
  • iOS version 10.0+
  • PINCache 2.3 — See instructions to add to your build process

Getting started

Within your app project in Xcode, add SCSDKCoreKit.framework, SCSDKLoginKit.framework, and SCSDKBitmojiKit.framework into General > Embedded Binaries.

Add the following fields in your application’s Info.plist file:

  • SCSDKClientId (string): Your application’s client ID
  • SCSDKRedirectUrl (string): The URL that will handle and complete login requests
  • SCSDKScopes (string-array): The scopes your application will request
  • LSApplicationQueriesSchemes (string-array): Must contain snapchat, bitmoji-sdk, and itms-apps
  • CFBundleURLSchemes (string-array): Must contain your redirect URL’s scheme — so if your redirect URL is my-app://abc/xy/z, this field would contain my-app

To handle login requests properly, add the following to your UIApplicationDelegate:

// swift

import SCSDKLoginKit

func application(_ app: UIApplication,
                 open url: URL,
                 options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
    let handled = SCSDKLoginClient.application(app, open: url, options: options)
    ...
}
// objc

#import <SCSDKLoginKit/SCSDKLoginKit.h>

- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
            options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options
{
    BOOL handled = [SCSDKLoginClient application:application
                                         openURL:url
                                         options:options];
    ...
}

Features

Avatar icon

The avatar icon is an image of your user that automatically refreshes to display the latest version of their avatar in your app. If the user is not logged in or does not have a Bitmoji, the element simply shows the Bitmoji logo.

Bitmoji Avatar

To implement the avatar icon, add an iconView:

// swift

import SCSDKBitmojiKit

let iconView = SCSDKBitmojiIconView()
// objc

#import <SCSDKBitmojiKit/SCSDKBitmojiKit.h>

UIView *iconView = [[SCSDKBitmojiIconView alloc] init];

You can also retrieve the URL of a user’s Bitmoji profile with the following snippet:

// swift

import SCSDKBitmojiKit

SCSDKBitmojiClient.fetchAvatarURL { (avatarURL: String?, error: NSError?) in
    // do something
}
// objc

#import <SCSDKBitmojiKit/SCSDKBitmojiKit.h>

[SCSDKBitmojiClient fetchAvatarURLWithCompletion:^(NSString *avatarURL, NSError *error) {
    // do something
}];

Sticker picker

The sticker picker is a visual interface that allows users to select Bitmoji stickers from the latest sticker catalog. Users can browse and search through the extensive Bitmoji library with the integrated UI.

Sticker Picker

To add the sticker picker UI, create a sticker picker view, and add a delegate to be notified whenever a user selects a sticker:

// swift

import SCSDKBitmojiKit

override func viewDidLoad() {
   super.viewDidLoad()
   ...
   let stickerPickerVC = SCSDKBitmojiStickerPickerViewController()
   stickerPickerVC.delegate = self

   addChildViewController(stickerPickerVC)
   view.addSubview(stickerPickerVC.view)
   stickerPickerVC.didMove(toParentViewController: self)
   ...
}

func bitmojiStickerPickerViewController(_ stickerPickerViewController: SCSDKBitmojiStickerPickerView,
                                        didSelectBitmojiWithURL bitmojiURL: String,
                                        image: UIImage?) {
   // do something
}

// Optional delegate method for listening to search field
// focus changes
func bitmojiStickerPickerViewController(_ stickerPickerViewController: SCSDKBitmojiStickerPickerView,
                                        searchFieldFocusDidChangeWithFocus hasFocus: Bool) {
   // do something
}
// objc

#import <SCSDKBitmojiKit/SCSDKBitmojiKit.h>

- (void)viewDidLoad
{
   [super viewDidLoad];
   ...
   SCSDKBitmojiStickerPickerViewController *stickerPickerVC = [[SCSDKBitmojiStickerPickerViewController alloc] init];
   stickerPickerVC.delegate = self;

   [self addChildViewController:stickerPickerVC];
   [self.view addSubview:stickerPickerVC];
   [stickerPickerVC didMoveToParentViewController:self];
   ...
}

- (void)bitmojiStickerPickerViewController:(SCSDKBitmojiStickerPickerViewController *)stickerPickerView
                   didSelectBitmojiWithURL:(NSString *)bitmojiURL
                                     image:(UIImage *)image
{
   // do something
}

// Optional delegate method for listening to search field
// focus changes
- (void)bitmojiStickerPickerViewController:(SCSDKBitmojiStickerPickerViewController *)stickerPickerView
        searchFieldFocusDidChangeWithFocus:(BOOL)hasFocus
{
   // do something
}

To enable Friendmojis, Bitmojis co-starring the current user and a friend, pass an external ID of another user to the sticker picker view:

// swift

import SCSDKBitmojiKit

override func viewDidLoad() {
   super.viewDidLoad()
   ...
   let friendUserId = ...
   let stickerPickerVC = SCSDKBitmojiStickerPickerViewController()
   stickerPickerVC.delegate = self
   stickerPickerVC.setFriendUserId(friendUserId)
   ...
}
// objc

#import <SCSDKBitmojiKit/SCSDKBitmojiKit.h>

- (void)viewDidLoad
{
   [super viewDidLoad];
   ...
   SCSDKBitmojiStickerPickerViewController *stickerPickerVC = [[SCSDKBitmojiStickerPickerViewController alloc] init];
   NSString *friendUserId = ...
   [stickerPickerVC setFriendUserId:friendUserId];

To remove a user’s Bitmoji content currently displayed in the app (either in avatar icons or in the sticker picker), unlink the user’s Snapchat account from your app.

To unlink a user who has connected their Snapchat account to your app, call the following snippet:

// swift

import SCSDKLoginKit

SCSDKLoginClient.unlinkCurrentSession { success in
    // do something
}
// objc

#import <SCSDKLoginKit/SCSDKLoginKit.h>

[SCSDKLoginClient unlinkCurrentSessionWithCompletion:^(BOOL success) {
    // do something
}];

That’s it! You just learned how to integrate the Bitmoji experience into your app, and how to unlink if needed.


Reference app

Need to see an example? Find our reference application on GitHub to see how the library can be integrated in a messaging app. Setup instructions are available in the README.md file.

iOS Chat

What’s next


Android

Bitmoji Kit Android gives you access to two Bitmoji features, the avatar icon and sticker picker. The avatar icon gives users a familiar visual identity within your app. The sticker picker lets users browse, search, and send Bitmojis.

Requirements

  • Android Studio 3.0+
  • Gradle 3.0+
  • Android API Level 19+

Getting started

First, add the following snippet to your build.gradle file:

 repositories {
    maven {
        url "https://storage.googleapis.com/snap-kit-build/maven"
    }
 }

Note: If you have trouble accessing Google (used in the link above), you can use our GitHub Maven repository with the following code block:

repositories {
   maven {
       url "https://raw.githubusercontent.com/Snap-Kit/release-maven/repo"
   }
}

Next, add the snippet below to the dependencies section of your application’s build.gradle file, not the root project’s build.gradle:

 dependencies {
    ...
    implementation([
            'com.snapchat.kit.sdk:bitmoji:1.1.4',
            'com.snapchat.kit.sdk:login:1.1.4',
            'com.snapchat.kit.sdk:core:1.1.4',
    ])
 }

Finally, add your application’s client ID, redirect URL, and scopes to the appropriate meta-data tags in your application’s AndroidManifest.xml:

 <uses-permission android:name="android.permission.INTERNET" />

 <application ...>
    <meta-data android:name="com.snapchat.kit.sdk.clientId" android:value="your app’s client id" />
    <meta-data android:name="com.snapchat.kit.sdk.redirectUrl" android:value="the url that will handle login completion" />
    <meta-data android:name="com.snapchat.kit.sdk.scopes" android:resource="@array/snap_kit_scopes" /> <!-- This should be a string array of scopes !-->

    ...

    <activity
        android:name="com.snapchat.kit.sdk.SnapKitActivity"
        android:launchMode="singleTask"
        >
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <!--
                Enter the parts of your redirect url below
                e.g. if your redirect url is my-app://abc/xy/z
                    android:scheme="my-app"
                    android:host="abc"
                    android:path="/xy/z"
            !-->
            <data
                android:scheme="the scheme of your redirect url"
                android:host="the host of your redirect url"
                android:path="the path of your redirect url"
                />
        </intent-filter>

    </activity>

    ...
 </application>

Note: By default, Bitmoji Kit uses the dependency versions listed below. If your application shares any of these dependencies, we recommend using similar versions to ensure consistent behavior.

 'com.android.support:appcompat-v7:26.1.0',
 'com.android.support:recyclerview-v7:26.1.0',
 'com.google.dagger:dagger:2.13',
 'com.squareup.okhttp3:okhttp:3.10.0',
 'com.squareup.retrofit2:retrofit:2.4.0',
 'com.squareup.retrofit2:converter-gson:2.4.0',
 'com.squareup.retrofit2:converter-wire:2.4.0',
 'com.squareup.wire:wire-runtime:2.3.0-RC1',
 'com.squareup.picasso:picasso:2.71828',

Features

Avatar icon

The avatar icon is an image of your user that automatically refreshes to display the latest version of their avatar in your app. If the user is not logged in or does not have a Bitmoji, the element simply shows the Bitmoji logo.

Bitmoji Avatar

If you are using a Fragment or a FragmentActivity from the Android support library, you may add it to your application as described below:

 getSupportFragmentManager().beginTransaction()
        .replace(R.id.icon_container /* The id of the icon container */, new BitmojiIconFragment())
        .commit();

You can also retrieve the URL of a user’s Bitmoji profile with the following snippet:

 Bitmoji.fetchAvatarUrl(context, new FetchAvatarUrlCallback() {
        @Override
        public void onSuccess(@Nullable String avatarUrl) {
            // do something
        }

        @Override
        public void onFailure(boolean isNetworkError, int statusCode) {
            // do something
        }
 });

Sticker picker

The sticker picker is a visual interface that allows users to pick Bitmoji stickers from the latest sticker catalog. Users can browse and search through the extensive Bitmoji library with this UI.

Sticker Picker

To add the sticker picker UI to your app, make sure you are using a Fragment or a FragmentActivity from the Android support library com.android.support:appcompat-v7:26.0.2 and add the code snippet below. This code inserts the sticker picker into a ViewGroup with the ID bitmoji_container in your layout.

 getSupportFragmentManager().beginTransaction()
        .replace(R.id.bitmoji_container /* The id of the sticker picker container */, new BitmojiFragment())
        .commit();

Note: The FragmentActivity that adds the BitmojiFragment must first already implement the OnBitmojiSelectedListener interface. This interface allows the application to be notified whenever a user selects a Bitmoji sticker from the st icker picker.

 @Override
 public void onBitmojiSelected(String imageUrl, Drawable previewDrawable) {
    // do something
 }

The FragmentActivity may also optionally implement the OnBitmojiSearchFocusChangeListener interface, which listens for users entering or exiting the search field:

 @Override
 public void onBitmojiSearchFocusChange(boolean hasFocus) {
    // do something
 }

To enable Friendmojis, Bitmojis co-starring the current user and a friend, pass an external ID of another user to the sticker picker view:

Fragment fragment = getSupportFragmentManager().findFragmentById(...);
if (fragment instanceof BitmojiFragment) {
    ((BitmojiFragment) fragment).setFriend(friendUserId);
}

Unlinking

To remove a user’s Bitmoji content currently displayed in the app (either in avatar icons or in the sticker picker), unlink the user’s Snapchat account from your app.

To unlink a user that has connected their Snapchat account, call the following:

SnapKit.unlink(context);

That’s it! You just learned how to integrate the Bitmoji experience into your app, and how to unlink if needed.

Reference app

Need to see an example? Find our reference application on GitHub to see how the library can be integrated in a messaging app.

Android Chat

Setup instructions are available in the README.md file.

What’s next


Web

Bitmoji Kit Web gives you access to the Bitmoji sticker picker feature. The sticker picker lets users browse, search, and send Bitmojis.

Requirements

Getting started

The main requirements for using Bitmoji Kit on web is that your network is able to access the javascript bundle login_bitmoji.js and Developer Portal options enabled.

Adding the sticker picker

The sticker picker is a visual interface that allows users to pick Bitmoji stickers from the latest sticker catalog. Users can browse and search through the extensive Bitmoji library with this UI.

Sticker Picker Not Logged In Sticker Picker Logged In

To add the sticker picker to your web client, follow the directions below for Adding Bitmoji Kit icon HTML example or jump straight to the full code here Adding Bitmoji Kit icon HTML example full code.

We recommend trying the client-side integration first. Although it’s not hooked up to a back end, this version lets you place a working sticker picker in your app. Once you see the result, move on to the server-side instructions. There, you’ll do the complete integration and retrieve long-lived access tokens so you can roll out this feature to users.

Client-side-only web application integration

Quickly integrate the Bitmoji sticker picker into your web app with this temporary access flow.

The OAuth2.0 implicit grant flow used in this integration provides a one-time access token. This means that when users click Continue with Snapchat and authorize your app, they get temporary access to the Bitmoji library and must renew it every hour via the UI.

We recommend starting here to get the sticker picker working. But before you roll out to users, consider setting up a server and following the server-side integration steps.

Adding Bitmoji Kit icon HTML example

First, add an HTML div to the page in your application where you want to add the sticker picker UI. Give your div element a unique class name like the one below. This div element will be the target for the Bitmoji SDK UI. More specifically, this is where the sticker picker UI button will be mounted.

/********************** HTML EXAMPLE **********************/
<html lang="en">
  <body>
    <div class="my-bitmoji-stickerpicker-icon-target" />
  </body>
</html>

Next, add a script tag into the the above HTML example to load the the SDK asynchronously.

/********************** HTML EXAMPLE **********************/
<html lang="en">
  <body>
    <div class="my-bitmoji-stickerpicker-icon-target" />
    <script>
      // Load the SDK asynchronously
      (function (d, s, id) {
        var js, sjs = d.getElementsByTagName(s)[0];
        if (d.getElementById(id)) return;
        js = d.createElement(s); js.id = id;
        js.src = "https://sdk.snapkit.com/js/v1/login_bitmoji.js";
        sjs.parentNode.insertBefore(js, sjs);
      }(document, 'script', 'bitmojikit-sdk'));
    </script>
  </body>
</html>

There is a callback that you will need to define which will let you know the SDK is loaded. The signature of this callback is:

window.snapKitInit = function () { // Add your code here }

Next, add the arguments required by mountBitmojiStickerPickerIcons (in the API) to mount the Bitmoji icon in the SDK callback.

/********************** HTML EXAMPLE **********************/
<html lang="en">
  <body>
    <div class="my-bitmoji-stickerpicker-icon-target" />
    <script>
      window.snapKitInit = function () {
        // Argument 1
        var bitmojiWebPickerIconClass =
          'my-bitmoji-stickerpicker-icon-target';

        // Argument 2
        var uiOptions = {
          onStickerPickCallback:
            function onStickerPickCallback(bitmojiImgURL){
              console.log(bitmojiImgURL);
            },
          webpickerPosition: 'bottomRight',
        };

        // Argument 3
        var loginParamsObj = {
          clientId: 'your-clientId',
          redirectURI: 'your-redirectURI',
          scopeList: [ // the list of scopes you are approved for
           'user.bitmoji.avatar',
           'user.display_name',
          ],
        };
      }

      // Load the SDK asynchronously
      (function (d, s, id){..}(document, 'script', 'bitmojikit-sdk'));
    </script>
  </body>
</html>

Refer to Sticker Picker Parameter Definitions for an explanation of each parameter in the API.

Finally, call the API to mount the Bitmoji icon. The signature for this API is:

mountBitmojiStickerPickerIcons(bitmojiWebPickerIconClass, uiOptions, loginParams);
/********************** HTML EXAMPLE **********************/
<html lang="en">
  <body>
    <div class="my-bitmoji-stickerpicker-icon-target" />
    <script>
      window.snapKitInit = function () {
        // Argument 1
        var bitmojiWebPickerIconClass =
          'my-bitmoji-stickerpicker-icon-target';

        // Argument 2
        var uiOptions = { .. };

        // Argument 3
        var loginParamsObj = { .. };

        // Mount Bitmoji Icon(s)
        snap.bitmojikit.mountBitmojiStickerPickerIcons(
          bitmojiWebPickerIconClass,
          uiOptions,
          loginParamsObj,
        );
      }

      // Load the SDK asynchronously
      (function (d, s, id) { .. } (document, 'script', 'bitmojikit-sdk'));
    </script>
  </body>
</html>

That’s it! You just integrated the Bitmoji sticker picker into your web app. Here is the full code:

Adding Bitmoji Kit icon HTML Example full code
/********************** HTML EXAMPLE **********************/
<html lang="en">
  <body>
    <div class="my-bitmoji-stickerpicker-icon-target" />
    <script>
       window.snapKitInit = function () {
        // Argument 1
        var bitmojiWebPickerIconClass =
          'my-bitmoji-stickerpicker-icon-target';

        // Argument 2
        var uiOptions = {
          onStickerPickCallback:
            function onStickerPickCallback(bitmojiImgURL){
              console.log(bitmojiImgURL);
            },
          webpickerPosition: 'bottomRight',
        };

        // Argument 3
        var loginParamsObj = {
          clientId: 'your-clientId',
          redirectURI: 'your-redirectURI',
          scopeList: [ // the list of scopes you are approved for
           'user.bitmoji.avatar',
           'user.display_name',
          ],
        };

        // Mount Bitmoji Icon(s)
        snap.bitmojikit.mountBitmojiStickerPickerIcons(
          bitmojiWebPickerIconClass,
          uiOptions,
          loginParamsObj,
        );
      };

      // Load the SDK asynchronously
      (function (d, s, id) {
        var js, sjs = d.getElementsByTagName(s)[0];
        if (d.getElementById(id)) return;
        js = d.createElement(s); js.id = id;
        js.src = "https://sdk.snapkit.com/js/v1/login_bitmoji.js";
        sjs.parentNode.insertBefore(js, sjs);
      }(document, 'script', 'bitmojikit-sdk'));
    </script>
  </body>
</html>
Server-side web application integration

The OAuth2.0 authorization grant flow we follow for this integration provides refreshable offline access tokens. These access tokens enable users to access features of the Bitmoji SDK and require the user to only authorize your application once. This approach is a bit more involved, with three main steps:

  1. Update the Sticker Picker integration code to override the login callback.
  2. Add backend server code to handle request/response from Snap’s authorization endpoints and manage token flows.
  3. Update the Bitmoji sticker picker component on your web client with the access token retrieved from your backend.

To write code for the server, use any language you’re comfortable in. We use JavaScript in our examples.

1. Update the sticker picker UI code to override login callback

Update the Sticker Picker integration code to override the login button’s onClick handler. By passing in a callback that calls a backend handler implemented by your application, you kick off the OAuth2.0 Authorization Code grant flow. Specify a callback parameter handleAuthGrantFlowCallback in the loginParamsObj.

Update the previous HTML EXAMPLE:

// Argument 1
var bitmojiWebPickerIconClass =
  'my-bitmoji-stickerpicker-icon-target';

// Argument 2
var uiOptions = {
  onStickerPickCallback:
    function onStickerPickCallback(bitmojiImgURL){
      console.log(bitmojiImgURL);
    },
  webpickerPosition: 'bottomRight',
};

// Argument 3
var loginParamsObj = {
  // Override this parameter `handleAuthGrantFlowCallback`
  handleAuthGrantFlowCallback:
    function handleAuthGrantFlowCallback(){
      // TO START THE OAUTH2.0 AUTHORIZATION
      // GRANT FLOW, POINT THIS CALLBACK TO
      // YOUR APPLICATION’S BACKEND HANDLER
    },
  clientId: 'your-clientId',
  redirectURI: 'your-redirectURI', // REMOVE THIS
  scopeList: ['your-scope(s)'], // REMOVE THIS
};
2. Add backend server code to handle request/response

See how your web server application can implement the OAuth2.0 authorization grant flow to access Snap data — for example, obtaining permission from the user to retrieve avatar data.

Adding the OAuth2.0 flow involves several steps.

Applications that implement this authorization type will be responsible for the following:

  • Managing the access token request flow for each user that authorizes your app
  • Managing the refresh flow for expiring access tokens
  • Managing the revocation flow for access tokens
  • Keeping their client secret and refresh tokens secure
2.1 Set up OAuth2.0 parameters

To make the initial redirect request to Snap’s authorization server, you need to generate the parameter: state.

ParameterDefinition
state"state” is a base64 URL encoded string. This value is used by the client to maintain state between the request and callback. The authorization server includes this value when redirecting the user-agent back to the client. The parameter SHOULD be used for preventing cross-site request forgery.

Feel free to use any language to generate the parameters’ values. We use JavaScript.

In JavaScript, the easiest way to generate these values is with the crypto module provided by NodeJS. It lets you make wrapper functions to create RFC-compliant values. See the crypto library helper below. The most important functions here are generateBase64UrlEncodedString(bytesToEncode) and generateRandomBytes(size) which help generate all three parameters.

// ******************** Crypto Library Helper ***************************
var _crypto = require('crypto');

var OAUTH2_STATE_BYTES = 32;
var REGEX_PLUS_SIGN = /\+/g;
var REGEX_FORWARD_SLASH = /\//g;
var REGEX_EQUALS_SIGN = /=/g;

/*
 * This function generates a random amount of bytes using the
 * crypto library
 *
 * @param {int} size - The number of random bytes to generate.
 *
 * @returns {Buffer} The generated number of bytes
 */
var generateRandomBytes = function generateRandomBytes(size) {
  return _crypto.randomBytes(size);
};

/*
 * This function encodes the given byte buffer into a base64 URL
 * safe string.
 *
 * @param {Buffer} bytesToEncode - The bytes to encode
 *
 * @returns {string} The URL safe base64 encoded string
 */
var generateBase64UrlEncodedString = function generateBase64UrlEncodedString(bytesToEncode) {
  return bytesToEncode
    .toString('base64')
    .replace(REGEX_PLUS_SIGN, '-')
    .replace(REGEX_FORWARD_SLASH, '_')
    .replace(REGEX_EQUALS_SIGN, '');
};

/*
 * This function generates the state required for both the
 * OAuth2.0 Authorization and Implicit grant flow
 *
 * @returns {string} The URL safe base64 encoded string
 */
var generateClientState = exports.generateClientState = function generateClientState() {
  return generateBase64UrlEncodedString(
    generateRandomBytes(OAUTH2_STATE_BYTES)
  );
};

You can use the function generateClientState() to help generate the parameter you need.

2.2 Redirect to Snap OAuth2.0 server

To redirect to the Snap authorization server, the OAuth2.0 parameters must be added as well.

Now that you have the query parameters generated, add the additional OAuth2.0 parameters.

ParameterDefinition
client_idThe client ID Snap assigned to your application when you signed up for Snap Kit, the value is a 36 character alphanumeric string.
client_secretThe client secret Snap assigned to your application when you signed up for Snap Kit. The value is a BASE64 URL encoded string.
redirect_uriThe redirect URI that you requested for your application.
scopeA URL safe space-delimited string of OAuth2.0 token scopes. These scope(s) were assigned to your application when you sign up for Snap Kit. These scopes handle what content your application can and cannot access.
As an example, if your application is assigned the OAuth2.0 scopes “ https://auth.snapchat.com/oauth2/api/example.abc” and “ https://auth.snapchat.com/oauth2/api/example.xyz” . Then your scope value would be: “https%3A%2F%2Fauth.snapchat.com%2Foauth2%2Fapi%2Fexample.abc%20https%3A%2F%2Fauth.snapchat.com%2Foauth2%2Fapi%2Fexample.xyz”
response_typeValue MUST be set to “code”

To authorize your application, you’ll build a GET request and redirect the user to it. The table below outlines the redirect endpoint and the query parameters required to access it.

Request URL For User Consent

TypeDescription
GET Requesthttps://accounts.snapchat.com/accounts/oauth2/auth
Queryclient id=<client id>&redirect uri=<redirect uri>&response_type=code&scope= < scope > &state= < state >

Note: The redirect endpoint can only be accessed via HTTPS.

Create a helper function to build out your URL.

// ******************** URL Builder Helper ***********************

var _qs = require('qs'); // Will need to 'npm install qs'

var getAuthCodeRedirectURL = function getAuthCodeRedirectURL(clientId, redirectUri, scopeList, state) {
  var SNAP_ACCOUNTS_LOGIN_URL = 'https://accounts.snapchat.com/accounts/oauth2/auth';
  var scope = scopeList.join(' ');
  var loginQS = {
    client_id: clientId,
    redirect_uri: redirectUri,
    response_type: 'code',
    scope: scope,
    state: state
  };

  var stringifyLoginQS = _qs.stringify(loginQS);
  return SNAP_ACCOUNTS_LOGIN_URL + '?' + stringifyLoginQS;
};

Now, create a quick ExpressJS application. In this example, whenever the user hits the the URL ‘http://localhost:3000/send-oauth-GET-request-step-two’, you’ll build the redirect URL and send the user to it.

// ******************** ExpressJS Server Main Logic ************************

var express = require('express'); // Will need to 'npm install express'
var app = express();

var clientId = 'my-assigned-client-id';
var clientSecret = 'my-assigned-client-secret';
var redirectUri = 'https://my-redirect-uri.com';
var scopeList = ['https://auth.snapchat.com/oauth2/api/example.abc', 'https://auth.snapchat.com/oauth2/api/example.xyz'];

app.get('/send-oauth-GET-request-step-two', function(req, res){
  // Generate query parameters
  var state = generateClientState();

  // Build redirect URL
  var getRedirectURL = getAuthCodeRedirectURL(clientId, redirectUri, scopeList, state);

  // Redirect user to get consent
  res.redirect(getRedirectURL);
});

app.listen(3000);

The redirect URL takes the user to Snapchat login.

After logging in, a page asks the user for consent to allow your application to retrieve the data it requests. In the example below, the application Bitmoji Chrome Extension asks for user consent to retrieve the user’s avatar data.

2.4 Handle OAuth2.0 server response

Your application needs to handle two scenarios for this step. The user can either approve or not approve your application’s requested scopes.

If the user approves your application, then an authorization code response will be sent as part of the URL parameter via the given redirect URI you specified in the original request. The response will contain an authorization “code” and the “state” that was originally sent. You will need need to validate that the “state” sent is equal to the “state” received. That response looks like this:

<redirect_uri>?code=123Abx23kdjfhdfjdf2&state=StYxxll233jdfjdlf

If the user does not approve your application, they’ll be redirected back to Snapchat login.

2.5 Exchange authorization code for refresh and access token

If the user gives consent to your application, you get an authorization code to retrieve the user’s access token. This authorization code expires within 10 minutes of grant. The required OAuth2.0 parameters for this step are outlined below.

ParameterDefinition
client_idThe client ID Snap assigned to your application when you signed up for Snap Kit, the value is a 36 character alphanumeric string.
client_secretThe client secret Snap assigned to your application when you signed up for Snap Kit. The value is a BASE64 URL encoded string.
redirect_uriThe redirect URI that you requested for your application.
grant_typePossible values include “authorization code” or “refresh token”
codeThe authorization code received from the authorization server.

Build a POST request with the header and payload (which includes authorization code from the OAuth2.0 response) outlined below.

Requesting an Access Token for A User

TypeDescription
POST Requesthttps://accounts.snapchat.com/accounts/oauth2/token
HeaderAuthorization: Basic BASE64(<client id>:<client secret>)
Payloadgrant type=authorization code&redirect uri=<redirect uri>&code= < code >

If the request is successful, the response returns these three values access_token, refresh_token, and expires_in. Persist these values in your backend; you’ll need this data to access Bitmoji SDK features and persist access.

// Success Response Body
{
    access_token: <string>,
    refresh_token: <string>,
    expires_in: <time in seconds>
}

If the request is not successful, the response returns the data error and error_description in the response body.

// Error Response Body
{
    error: <ascii error code>,
    error_description: <human readable error description>
}

Update your previous ExpressJS example to include requesting access token for a user. You’ll use an additional package, called ‘request’, to make HTTP requests. In this example, whenever the user hits the the URL ‘http://localhost:3000/send-access-token-POST-request-step-five’, you’ll build the POST request and send it to Snapchat’s authorization endpoint.

// ******************** ExpressJS Server Main Logic ************************

var express = require('express'); // will need to 'npm install express'
var request = require('request'); // will need to 'npm install request'

var app = express();

var clientId = 'my-assigned-client-id';
var clientSecret = 'my-assigned-client-secret';

var redirectUri = 'https://my-redirect-uri.com';
var scopeList = ['https://auth.snapchat.com/oauth2/api/example.abc', 'https://auth.snapchat.com/oauth2/api/example.xyz'];

app.get('/send-oauth-GET-request-step-two', function(req, res){
   // ..
});

app.get('/send-access-token-POST-request-step-five', function(req, res) {
  var SNAPCHAT_AUTH_ENDPOINT = 'https://accounts.snapchat.com/accounts/oauth2/token';
  var auth_code = 'received-auth-code-xyz';

  var authorizationHeader = clientId + ':' + clientSecret;
  var authorizationHeaderBase64 = Buffer.from(authorizationHeader).toString('base64');

  // Set headers
  var headers = {
    'Content-Type': 'application/x-www-form-urlencoded',
    'Authorization': 'Basic ' + authorizationHeaderBase64
  }

  // Configure access token POST request
  var options = {
    url: SNAPCHAT_AUTH_ENDPOINT,
    method: 'POST',
    headers: headers,
    form:{
      grant_type: 'authorization_code',
      code: auth_code,
      redirect_uri: redirectUri,
      client_id: clientId,
    }
  };

  // Start POST request
  request(options, function (error, response, body) {
      // Handle success and error responses here
      // Make sure to persist access_token, refresh_token, and expires_in
      res.send(response)
  })
});

app.listen(3000);
2.6 (Offline) Refreshing access token

The access_token retrieved expires hourly, but it can be refreshed offline without user consent. Find the expiry data in expires_in and have your application refresh the access_token before that expiry. Use the required OAuth2.0 parameters below for this step.

ParameterDefinition
client_idThe client ID Snap assigned to your application when you signed up for Snap Kit, the value is a 36 character alphanumeric string.
client_secretThe client secret Snap assigned to your application when you signed up for Snap Kit. The value is a BASE64 URL encoded string.
grant_typePossible values include “authorization code” or “refresh token”
refresh_tokenThe users refresh token received from the authorization server. Will need to be used when refreshing an expiring access_token.

In order to refresh access, build a POST request with the header and payload outlined below.

Refreshing An Access Token For A User

TypeDescription
POST Requesthttps://accounts.snapchat.com/accounts/oauth2/token
HeaderAuthorization: Basic BASE64(<client id>:<client secret>)
Payloadgrant type=refresh token&refresh token=<refresh token>

If the request is successful, the the response body returns a new set of data for access_token, refresh_token, and expires_in. You will need update these values in your backend.

// Success Response Body
{
    access_token: <string>,
    refresh_token: <string>,
    expires_in: <time in seconds>
}

If the request is not successful, the response returns the data error and error_description in the response body.

// Error Response Body
{
    error: <ascii error code>,
    error_description: <human readable error description>
}

Update your ExpressJS example to include requesting access token for a user. You'll use an additional package called ‘request’ to help make HTTP requests. In this example, whenever the user hits the the URL ‘http://localhost:3000/send-refresh-token-POST-request-step-six’, you'll build the POST request and send it to Snapchat’s authorization endpoint.

// ******************** ExpressJS Server Main Logic ************************

var express = require('express'); // will need to ‘npm install express`
var request = require('request'); // will need to ‘npm install request`

var app = express();

var clientId = 'my-assigned-client-id';
var clientSecret = 'my-assigned-client-secret';

var redirectUri = 'https://my-redirect-uri.com';
var scopeList = ['https://auth.snapchat.com/oauth2/api/example.abc', 'https://auth.snapchat.com/oauth2/api/example.xyz'];

app.get('/send-oauth-GET-request-step-two', function(req, res){
   // ..
});

app.get('/send-access-token-POST-request-step-five', function(req, res) {
  // ..
});

app.get('/send-refresh-token-POST-request-step-six', function(req, res) {
  var SNAPCHAT_AUTH_ENDPOINT = 'https://accounts.snapchat.com/accounts/oauth2/token';

  var authorizationHeader = clientId + ':' + clientSecret;
  var authorizationHeaderBase64 = Buffer.from(authorizationHeader).toString('base64');

  // Set headers
  var headers = {
    'Content-Type': 'application/x-www-form-urlencoded',
    'Authorization': 'Basic ' + authorizationHeaderBase64
  }

  // Configure refresh token POST request
  var options = {
    url: SNAPCHAT_AUTH_ENDPOINT,
    method: 'POST',
    headers: headers,
    form:{
      grant_type: 'refresh_token',
      refresh_token: refresh_token, // refresh_token is value from step six
    }
  };

  // Start POST request
  request(options, function (error, response, body) {
      // Handle success and error responses here
      // Persist new access_token, refresh_token, and expires_in values
      res.send(response)
  })
});

app.listen(3000);
2.7 (Offline) Revoking access token

Sometimes a user might want to revoke access to your application, which they can do from the Snapchat accounts page. We also recommend providing users the option of revoking access via your UI. Use the required OAuth2.0 parameters below for this step.

ParameterDefinition
client_idThe client ID Snap assigned to your application when you signed up for Snap Kit, the value is a 36 character alphanumeric string.
client_secretThe client secret Snap assigned to your application when you signed up for Snap Kit. The value is a BASE64 URL encoded string.
refresh_tokenThe users refresh token received from the authorization server. Will need to be used when refreshing an expiring access_token.

If the user wants to revoke access, you will need to build a POST request with the Header and Payload outlined below

Revoking an Access Token for a User

TypeDescription
POST Requesthttps://accounts.snapchat.com/accounts/oauth2/revoke
HeaderAuthorization: Basic BASE64(<client id>:<client secret>)
Payloadtoken=<refresh_token>

Whether or not the request succeeds, we return server response 200. Regardless of response status, you must discard the user’s access_token and refresh_token.

Update your ExpressJS example to include revoking an access token for a user. In this example, whenever the user hits the the URL ‘http://localhost:3000/send-revoke-token-POST-request-step-seven’, you build the POST request to revoke the token and send it to Snapchat’s authorization endpoint.

// ******************** ExpressJS Server Main Logic ************************

var express = require('express'); // Will need to 'npm install express'
var request = require('request'); // Will need to 'npm install request'

var app = express();

var clientId = 'my-assigned-client-id';
var clientSecret = 'my-assigned-client-secret';

var redirectUri = 'https://my-redirect-uri.com';
var scopeList = ['https://auth.snapchat.com/oauth2/api/example.abc', 'https://auth.snapchat.com/oauth2/api/example.xyz'];

app.get('/send-oauth-GET-request-step-two', function(req, res){
   // ..
});

app.get('/send-access-token-POST-request-step-five', function(req, res) {
  // ..
});

app.get('/send-refresh-token-POST-request-step-six', function(req, res) {
  // ..
});

app.get('/send-revoke-token-POST-request-step-seven', function(req, res) {
  var SNAPCHAT_AUTH_REVOKE_ENDPOINT = 'https://accounts.snapchat.com/accounts/oauth2/revoke';

  var authorizationHeader = clientId + ':' + clientSecret;
  var authorizationHeaderBase64 = Buffer.from(authorizationHeader).toString('base64');

  // Set headers
  var headers = {
    'Content-Type': 'application/x-www-form-urlencoded',
    'Authorization': 'Basic ' + authorizationHeaderBase64,
  }

  // configure refresh token POST request
  var options = {
    url: SNAPCHAT_AUTH_REVOKE_ENDPOINT,
    method: 'POST',
    headers: headers,
    form:{
      token: refresh_token, // refresh_token is value from step six
    }
  };

  // Start POST request
  request(options, function (error, response, body) {
      // Clear access_token, refresh_token, and expires_in values
      res.send(response)
  })
});

app.listen(3000);
3. Update Bitmoji sticker picker UI

The last step of this process is to update your client code to set the retrieved access_token or any time a new access_token is retrieved via the refresh flow. The updated signature for the APIs are:

mountBitmojiStickerPickerIcons(bitmojiWebPickerIconClass, uiOptions, loginParams, accessToken);