Skip to content

Instantly share code, notes, and snippets.

@erorus
Last active March 6, 2019 02:41
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save erorus/6c08227921ff99d93295fa9f91c7fd70 to your computer and use it in GitHub Desktop.
Save erorus/6c08227921ff99d93295fa9f91c7fd70 to your computer and use it in GitHub Desktop.
Mashery -> Blizzard API Migration

Mashery -> Blizzard API Migration

This is intended for developers who are currently using the Battle.net API via Mashery, and need to migrate to Blizzard's own Battle.net API.

The official migration documentation is here but it's wordy and scattered. This document intends to cut the BS for existing developers as a true migration guide.

It's organized into sections based on the different kinds of API calls.

Game Note

This was written with World of Warcraft APIs in mind. While our hostnames are changing, none of WoW's API paths will change. However, some Starcraft II paths will change, so please reference Blizzard's documentation for further information about that.

Community OAuth Profile APIs

Purpose: These APIs are used for logging in users via their Blizzard account, getting the user's battle tag and characters.

New Docs: Blizzard documentation and endpoint update thread

Migration:

  1. Get new app credentials here. Same story as Mashery, you tell it your app name and it gives you a new Client ID and Client Secret. Rate limit is the same.
  2. The /account/user endpoint moved to /oauth/userinfo
  3. The TW and KR region hosts are now apac.battle.net.
  4. All endpoints starting with /oauth are hosted at the OAuth authorize/token host (e.g. us.battle.net).
  5. Other endpoints not starting with /oauth appear to use the Game Data/Community hosts (despite contradictory documentation).

Full list of OAuth API endpoints: (which use the Authorization Code flow at OAuth hosts)

Old New
/oauth/authorize /oauth/authorize
/oauth/token /oauth/token
/account/user /oauth/userinfo
/oauth/check_token?token=

Full list of OAuth hosts: (which differ from the Game Data and Community API hosts)

Region Old New
US us.battle.net us.battle.net
EU eu.battle.net eu.battle.net
TW tw.battle.net apac.battle.net
KR kr.battle.net apac.battle.net
CN www.battlenet.com.cn www.battlenet.com.cn

Full list of Profile API endpoints: (which use the Authorization Code flow at Game Data API hosts (see below))

  • /sc2/profile/user
  • /wow/user/characters

Game Data APIs

Purpose: These are the newer APIs that Blizzard introduced on Mashery, for stuff like connected realms, WoW Token prices, Mythic leaderboards, etc. They use that OAuth client credentials flow.

New Docs: Blizzard documentation

Migration: You'll need a new Client ID and Secret, and hit different hostnames. That's it.

  1. Get new app credentials here. Same story as Mashery, you tell it your app name and it gives you a new Client ID and Client Secret. Rate limit is the same.
  2. Use new hostnames for the API calls. The hostnames to get the OAuth access token is mostly the same as before (see above).
Region Old New
US us.api.battle.net us.api.blizzard.com
EU eu.api.battle.net eu.api.blizzard.com
TW tw.api.battle.net tw.api.blizzard.com
KR kr.api.battle.net kr.api.blizzard.com
SEA sea.api.battle.net sea.api.blizzard.com
CN api.battlenet.com.cn gateway.battlenet.com.cn

Community APIs

Purpose: These are the original APIs that you know and love and probably use the most. Achievements, items, spells, character profiles, guilds, etc.

New Docs: Blizzard documentation

Migration: These now use the same hosts and authentication as the Game Data APIs. Migration depends on if you already use Game Data APIs or not.

"I already use Game Data APIs"

Follow the migration steps for the Game Data APIs, and use the new hostnames as mentioned above. Instead of the "apikey" parameter in the URL, use the client credentials flow for these, too.

"I haven't used Game Data APIs before"

OK, so back on Mashery, when you made an API request, you would add your API key on the end of the URL, like this:

https://us.api.battle.net/wow/achievement/2144?apikey=ABCD1234

That API key was the same every time, and things were easy. With the OAuth client credentials flow, we don't use that raw API key anymore. Instead we use an access token which expires after a little while. Don't be scared, it's not as hard as it sounds. It will look like this:

https://us.api.blizzard.com/wow/achievement/2144?access_token=asdfASDFasdfASDF

  1. Get new app credentials here. Same story as Mashery, you tell it your app name and it gives you a new Client ID and Client Secret. Rate limit is the same.
  2. Get your access token. Blizzard actually does a decent job on that page describing how to get a token, but I'll tell you how I do it anyway:
    1. Find your token URI. It's probably https://us.battle.net/oauth/token

    2. Send a GET request with your client ID and Secret: https://us.battle.net/oauth/token?grant_type=client_credentials&client_id=CLIENTID&client_secret=CLIENTSECRET

    3. You'll get back JSON that looks like this:

       {
           "access_token":"asdfASDFasdfASDF",
           "token_type":"bearer",
           "expires_in":86399
       }
      
    4. There's your access token, and "expires_in" tells you for how many seconds it'll work. It used to be for about a month, but now it looks like a day.

  3. Use new hostnames for your requests. The paths themselves remain the same.
    Old: us.api.battle.net
    New: us.api.blizzard.com
  4. Send your GET request.
    https://us.api.blizzard.com/wow/achievement/2144?access_token=asdfASDFasdfASDF

Client Credentials Flow Recap

  • Instead of ?apikey=YOUR_PERMANENT_KEY you'll add ?access_token=YOUR_TEMPORARY_TOKEN
  • You get that token via a request to the OAuth Token URI, with grant_type=client_credentials and your client ID and Secret.
  • Since that requires your secret, you don't want to execute your token call on a client. You'll want a server somewhere to do that. Then your server can give the token to the client, and the client can make the rest of the calls with that.
@dawg6
Copy link

dawg6 commented Oct 29, 2018

If you are super concerned about security, you can pass the acces_token in the HTTP Request header instead of as a query parameter in the URL. I found that if you try to use the new SC2 APIs (which aren't actually active yet), you get redirected to a very long URL that includes the query parameters in your request URL (including the access_token). By passing it in the Request Header instead, you avoid potentially exposing the access_token.

To put the access_token in the Request Header, set the Header property "Authorization" equal to "Bearer XXXXX" (where XXXXX is the access_token).

@maxnechaev
Copy link

Thanks for the article. Just a small correction in

Send a GET request with your client ID and Secret: https://us.battle.net/oauth/token?grant_type=client_credentials&client_id=CLIENTID&client_secret=CLIENTSECRET

That should be POST request I suppose. Here is the link.

@erorus
Copy link
Author

erorus commented Nov 16, 2018

Send a GET request with your client ID and Secret: https://us.battle.net/oauth/token?grant_type=client_credentials&client_id=CLIENTID&client_secret=CLIENTSECRET

That should be POST request I suppose. Here is the link.

I just confirmed that GET requests do work as I described.

@thach1ef
Copy link

Fairly new to all this. Does this mean that I have to get a new token and edit my code every time the previous token expires?

@kaelonR
Copy link

kaelonR commented Jan 12, 2019

No, tokens are only valid for 24 hours so it would be a bit tedious to need to edit your code every time a token expires.

To use the new OAuth flow you'll need to send a POST request to https://{region}.battle.net/oauth/token with three parameters:

grant_type=client_credentials
client_id=\<your client id\>
client_secret=\<your client secret\>

That will give you a response that looks like this:

 {
     "access_token":"asdfASDFasdfASDF",
     "token_type":"bearer",
     "expires_in":86399
 }

you'll need to save the access code somewhere, like in a database or in a text file, along with when the token expires.

Then everytime you (your code) needs to make a request to the API, it should read this token from the DB or text file and check whether the token is still valid. If it's expired, repeat above process to get a new token. If the token is still valid, proceed to send a request to the API and include this header in the request:
Authorization: bearer <your access token>

This process is basically a replacement for the Api key to make sure that if your API credentials get leaked/stolen, they are only valid for a day at max and can't be abused forever. It does make the process of getting Data from the APIs a bit more complicated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment