Guide to the Black Lion Trading Co API
The Talcmaster.7391:
Since we now have a dedicated spot for API discussions, I figured I would take the liberty of sharing what I know about the Trading Post / Gem Store API so that anyone interested in making something with it will have a thorough reference to go off of. Thanks to all the people in the #gw2spidy chatroom who showed me much of this.
DISCLAIMER: This API is not an official-release API and is not intended for public use. Therefore, it is unsupported by Arenanet, NCsoft or any other company. It is subject to change without any notification. USE AT YOUR OWN RISK.
Web addresses involved:
- https://tradingpost-live.ncplatform.net – trading post page
- https://gemstore-live.ncplatform.net – gem store page
- https://exchange-live.ncplatform.net – gem exchange page
Accessing the Trading Post:
The external login page is /authenticate after one of the above address:
- https://tradingpost-live.ncplatform.net/authenticate
- https://gemstore-live.ncplatform.net/authenticate
- https://exchange-live.ncplatform.net/authenticate
These pages use a fairly standard SSO (Single Sign On) setup, so if you are already logged into the forum, it will check against the forum and automatically redirect you to that particular site’s landing page. If you are not logged in, it will redirect you to account.guildwars2.com so you can enter your information. If you already have a valid session ID, you can add it as a parameter: <site>/authenticate?id=<session-id>
If, like me, you are trying to access these parameters outside of a web browser and don’t retain cookies, you can add the session-id in the form of s=<session-id> as a custom header called Cookie (this is how cookies are automatically passed in a browser) whenever you make an API call.
Note that session-ids do expire, and you will need to update these regularly or finding a way of retrieving a new one automatically as necessary.
tradingpost outputs:
- https://tradingpost-live.ncplatform.net/ws/search.json
This output is the one that does the majority of functions on the TP. By default it won’t return anything as it requires a combination of different parameters depending on what you are trying to accomplish. - ?text=&levelmin=0&levelmax=80
This combination will return a list of all the items along with their buy and sell listings and prices. By default this only returns 10 items at a time, but this is adjustable by the count= parameter. If count=0 it will return all of the items in the list. The offset= parameter starts the listing based on that number in the list (1 is the first item) The text= can be filled in to filter by the item name, but leaving it blank is still valid. levelmin and levelmax require valid numbers to be entered. Other filters that are optional are removeunavailable=true, rarity=, type=, and subtype= (these last 3 require their numeric representation, not characters). WARNING: This can pull in ALL ITEMS and can take a long time to run and take a great deal of memory to process - ?text=text&typeahead=1
This combination returns just the type, id, and name of an item. This is what is called when you type something into the search box and it gives you a list of items. It requires some sort of text to be entered to work. The count=0 trick works on this as well, and you can use offset= as well. Optional parameters levelmin, levelmax, removeunavailable, rarity, type, and subtype all function the same as above. - ?ids=27321,24354
This allows you to enter a comma delimited list of item ids (up to 250) and pull in the same info as you do from the first set of parameters. All of the other parameters are rendered inoperable when this parameter is specified.
Continued in next post…
The Talcmaster.7391:
…Continued from above
- https://tradingpost-live.ncplatform.net/ws/listings.json?id=27321
This will pull in the buy and sell listings for the first 20 prices as seen when you click on a specific item in the trading post. It returns the price, number of listings at that price, and the total of numbers ordered at that price. If you specify type=buys or type=sells it will return that type, but by default returns both. The data is not all listings for an item, and since only one item can be returned at a time is a much slower way of getting data out than search.json so if you have no reason to look at specific listings, just stick to search.json
- https://tradingpost-live.ncplatform.net/ws/trends.json
This odd little output shows all the trending information you see on the main page. It has all the standard item information for the items, and a list if IDs for each category. There are no parameters for it, and may not even be up to date at a given time. I would not rely on it for much, but am including it here for the sake of completeness.
- https://tradingpost-live.ncplatform.net/ws/me.json
This output actually requires a session-id that originates in game to be able to access. I won’t get into how to retrieve that particular session-id. This is what you see when you view your transactions, and requires a combination of parameters to return a valid result. The type=buy or type=sell will return either your buy or sell transactions respectively. The time=now or time=past shows either your current listings or your historical transactions.
gemstore outputs:
- https://gemstore-live.ncplatform.net/ws/search.json
This outputs all of the information about a given gemstore item and requires either the discounted=1 parameter, the category= parameter, or the text= to return a valid list. Using a combination will limit it further. The category= uses actual words for the categories, and the following are valid: decorative, consumable, convenience, boosts, minipets, account. The text= parameter must have a valid text search after it to return results. Optional parameters are offset and count, which behave the same as the tradingpost search.json.
- https://gemstore-live.ncplatform.net/ws/history.json
This outputs items previously bought on the gemstore, and requires a session-id that originates from the game. It is the same information as the search returns, except historical based on your account. The only known parameter is count=
exchange outputs:
- https://exchange-live.ncplatform.net/ws/trends.json
This outputs the raw data powering the little graph seen on the bottom of the exchange. With no type specified, it by default outputs the equivalent of a type=ReceivingCoins parameter, with the gem counterpart being type=ReceivingGems.
- https://exchange-live.ncplatform.net/ws/rates.json
This is another one that requires a session-id from the game. It is what provides the conversion rates between coins and gems. It requires a coins= and/or gems= number parameter added on to return values of that type. I have not managed to get this to successfully work myself, so I think this also requires some sort of character id to be passed. I do know that it is how Gw2spidy and some others pull in data.
That’s pretty much everything I know about these APIs. If there is anything I missed that needs to be clarified or if you have anything to share, let me know and I will add it.
marnick.4305:
Is it possible to buy with this api or merely watch prices?
DarkSpirit.7046:
Is it possible to buy with this api or merely watch prices?
Yes it is possible to buy. For buy, you have to do a https post
https://tradingpost-live.ncplatform.net/ws/item/<itemId>/buy
with the following parameters:
{count=int,price=int,charid=<char guid>}
You also need your game session key.
Killer Rhino.6794:
The Talcmaster, this is phenomenal! Thank you!
The Talcmaster.7391:
I believe it is possible to do any of the functions that you can do normally in those pages, such as buying and selling items, buying and redeeming gems, buying gemstore items, etc. I haven’t played with any of these functions because 1) I don’t know how to retrieve my charid, 2) I don’t want to mess with things that can cause permanent unwanted changes, and 3) I’m currently only interested in pulling out the data so I can create some nifty visualizations. I didn’t mention them in the doc for much the same reasons, as well as not wanting to be responsible for people playing with things they may regret. Of course, I welcome DarkSpirit and other people who have played with it to add to this in their own posts and make it more thorough and complete.
Healix.5819:
Selling and picking up items are done directly though the client. Basically, you can’t “touch” items through the API.
The charid has to be intercepted by either reading memory or the url used to authenticate. The in-game session key has to be obtained the same way or by reading the cookie file located in gw2cache.
DarkSpirit.7046:
I would be surprised if ArenaNet finally decides to release their trading post API as it is right now. I don’t think it is ready.
Most of the interesting functions require the game session key and char id guid and having this requirement hampers their use in mobile apps, which is why I didn’t post any detail information about their Trading Post API. I also would not know what I post would be outdated by the time ArenaNet decides to officially release this.
However, since The Talcmaster has already posted this information, I can help by supplementing any info that he may have missed out.
DarkSpirit.7046:
If you want complete C# code using this API, you can look at Zicore’s TP Notifier:
https://forum-en.guildwars2.com/forum/game/bltc/Zicore-s-Trading-Post-Notifier-Open-Source/first
It uses .NET 4.0. I have also written my own C# app in .NET 4.5 (for its async programming) but it is still work-in-progress.
Here are some of the enums that I use:
public enum RarityEnum
{
Junk = 0,
Basic,
Fine,
Masterwork,
Rare,
Exotic,
Ascended,
Legendary
};
public enum TypeEnum
{
Armor = 0,
Back = 1,
Bag = 2,
Consumable,
Container,
[EnumMember(Value = “CraftingMaterial”)]
Crafting_Material,
Gathering,
Gizmo,
MiniPet = 11,
Tool = 13,
Trinket = 15,
Trophy,
[EnumMember(Value = “UpgradeComponent”)]
Upgrade_Component,
Weapon
};
// for TypeEnum.Armor
public enum ArmorSubTypeEnum
{
Coat = 0,
Leggings,
Gloves,
Helm,
[EnumMember(Value = “HelmAquatic”)]
Aquatic_Helm,
Boots,
Shoulders
};
// for TypeEnum.Consumable
public enum ConsumableSubTypeEnum
{
Alcohol = 1,
Generic,
Food = 3,
Tonics = 4, // Suppose to be Generic?
Transmutation = 5,
Unlock,
Skins = 7,
Dyes_and_Recipes = 8, // Suppose to be Unlock?
Utility = 9,
[EnumMember(Value = “ContractNpc”)]
Contract_Npc,
[EnumMember(Value = “AppearanceChange”)]
Appearance_Change,
Immediate,
Halloween
};
// for TypeEnum.Container
public enum ContainerSubTypeEnum
{
Default = 0,
[EnumMember(Value = “GiftBox”)]
Gift_Box
};
// for TypeEnum.Gathering
public enum GatheringSubTypeEnum
{
Foraging = 0,
Logging,
Mining
};
// for TypeEnum.Gizmo
public enum GizmoSubTypeEnum
{
Default = 0,
Salvage = 2,
[EnumMember(Value = “RentableContractNpc”)]
Rentable_Contract_Npc,
[EnumMember(Value = “UnlimitedConsumable”)]
Unlimited_Consumable
};
// for TypeEnum.Tool
public enum ToolSubTypeEnum
{
Crafting = 0,
Salvage = 2
};
// for TypeEnum.Trinket
public enum TrinketSubTypeEnum
{
Accessory = 0,
Amulet,
Ring
};
// for TypeEnum.UpgradeComponent
public enum UpgradeComponentSubTypeEnum
{
Default = 0,
Gem = 1,
Rune = 2,
Sigil = 3
};
// for TypeEnum.Weapon
public enum WeaponSubTypeEnum
{
Sword = 0,
Hammer,
[EnumMember(Value = “LongBow”)]
Long_Bow,
[EnumMember(Value = “ShortBow”)]
Short_Bow,
Axe,
Dagger,
Greatsword,
Mace,
Pistol,
Rifle = 10,
Scepter,
Staff,
Focus,
Torch,
Warhorn,
Shield,
[EnumMember(Value = “Harpoon”)]
Spear = 19,
[EnumMember(Value = “Speargun”)]
Harpoon_Gun,
Trident,
[EnumMember(Value = “TwoHandedToy”)]
Toy
};
Note that there are currently some bugs surrounding ArenaNet’s search filters. They don’t have Back Item search and some of the consumable sub types that I have above, implemented in their TP dialog web page. So keep in mind that these enums may change by the time ArenaNet releases this api.
The Talcmaster.7391:
I totally agree, DarkSpirit. As it stands, the API that the trading post comes with exists primarily for facilitating its in game functionality, which is why it is a little bit more confusing than the newer API stuff just released. It was built a bit with external applications in mind, otherwise it wouldn’t be accessible outside the game at all. This hasn’t stopped people from figuring out how to pull all sorts of useful information from it and building those many excellent sites. I’ve been informed that the ability to check prices without needing to authenticate may be in the cards but right now it is necessary to prevent people from abusing the TP with too many calls. I don’t expect this to be truly outdated any time soon since right now is more of a focus on making new information available. The only changes that I know of was the last release adding the count= parameter to the trading post’s search.json and the release before that making the listings.json not require an in-game session-id. If people let me know about small changes like that, I’ll try my best to keep this up to date.
DarkSpirit.7046:
Thanks for the update, The Talcmaster. Personally, I am so glad that they added the count parameter to the trading post’s search.json. My app sorting feature for computed columns, is much faster now.
I would be very excited when they officially release their trading post api.
The Talcmaster.7391:
Yeah, that count feature reduced the run time of my ETL from around an hour to less than a minute. Being able to pull in item and recipe information from the game itself will go a long way towards making people’s Trading post apps more robust than before.
zaced.7948:
dear dudes and dudesses from anet. this thread needs a sticky before it leaves the front page and people start making new threads with the same questions over and over again.
centralist organization always pays off in terms of administration efficiency, i won’t mention examples since you probably are selling copies there.
greetings
zach
anzenketh.3759:
dear dudes and dudesses from anet. this thread needs a sticky before it leaves the front page and people start making new threads with the same questions over and over again.
centralist organization always pays off in terms of administration efficiency, i won’t mention examples since you probably are selling copies there.
greetings
zach
Problem is I don’t think they want it there yet. This API is not likely the one ready for Prime Time.
DarkSpirit.7046:
I have updated my enums above as best as I can with the current schema from the items api shown here:
http://wiki.guildwars2.com/wiki/API/item_details
There are still some confusion with the subtypes because the items api returns strings while the TP api returns integer ids. Plus the fact that there are existing bugs surrounding the TP search filters so items may not have been listed correctly on the TP at the moment. However, in the context of the TP, they should not matter since the items in the new enums, returned by the items api, are bounded and are not able to be traded in the TP.
If my enum value is spelled differently as the strings returned from the items api, I have indicated those through the EnumMember attribute.
athanor.7410:
There is a JAVA implementation here:
Java class
You can connect and get trading post outputs
Lil Puppy.5216:
Does the parameter &weight=[0,1,2] no longer do anything? I think it was 0,1,2 but it might be 1,2,3. It was used to filter out light, medium, and heavy armor types in the beginning.
tested 1: yep, it doesn’t do anything now… that’s a shame since it worked beautifully.
tested 2: &weightclass=[integer] is a parameter but integer values don’t return anything useful – still getting mixed weight classes returned (heavy,medium,light).
https://tradingpost-live.ncplatform.net/ws/search.json?text=&levelmin=80&levelmax=80&rarity=5&type=0&weightclass=0
Returns Aidan’s medium armors and just after that is Apothecary’s Draconic heavy armors.
{
"args": {
"offset": 1,
"count": 10,
"rarity": 5,
"weightclass": 0,
"levelmin": 80,
"levelmax": 80,
"type": 0
},
"total": "326",
"results": [
{
"type_id": "3",
"data_id": "323",
"item_image_hash": "761944b",
"guid": "AD0B4245-74D8-4713-88D2-EABA36DEF013",
"name": "Aidan's Boots",
"description": "",
"level": "80",
"rarity": "5",
"vendor": "264",
"sell_price": "30192",
"sell_count": "101",
"buy_price": "21801",
"buy_count": "127",
"passwords": [],
"rarity_word": "Exotic",
"img": "https://dfach8bufmqqv.cloudfront.net/gw2/img/content/761944b_icon_small.png",
"tradeable": true
}, {...}
]
}
DarkSpirit.7046:
Interesting, I never knew that the TP server supported armor weight class filtering. My app search function simply applies a second filter to the returned result matched against the weight class specified by the official API or GW2DB, if armor weight class is specified by the user.
Lil Puppy.5216:
During beta the check box that currently filters things that are currently available was used to filter items the character could use like armor and weapons. The API had it as &weight=[int] parameter, now &weightclass=[int].
enjoyaol.2398:
Any way to get the historical prices of the items from the API ? (sell and buy sides)
Right now I’m using GW2Spidy api but relying on GW2 servers would be better for me.
thx !
Killer Rhino.6794:
Any way to get the historical prices of the items from the API ? (sell and buy sides)
Right now I’m using GW2Spidy api but relying on GW2 servers would be better for me.
thx !
Nope. In order to aggregate TP data over time, you would need to do exactly what gw2spidy.com is already doing, which is to say, constantly poll, collect and store the TP data in some manner.
If you don’t want to rely on gw2spidy.com remotely, you can fire up your own version of the site. For some time, the author of gw2spidy.com has graciously open sourced his code and provided detailed instructions on how to use it on the project’s GitHub page
Shameless Plug: If you want to write iOS or OS X apps which can query gw2spidy.com, check out GW2Kit
BlazingZero.9702:
hello everyone, firstly thank you The Talcmaster for creating this awesome post. This really helps a lot for people like me who want to write a bit of program to access the TP outside of the game.
As I’m pretty new to using JSON, I would like to know how can I authenticate myself when accessing the TP? I’m using C# on Unity.
DarkSpirit.7046:
hello everyone, firstly thank you The Talcmaster for creating this awesome post. This really helps a lot for people like me who want to write a bit of program to access the TP outside of the game.
As I’m pretty new to using JSON, I would like to know how can I authenticate myself when accessing the TP? I’m using C# on Unity.
The purpose of authenticating is to obtain a session key which you can then set in your cookie (i.e. s=<your session key guid>) to accompany further transactions with the TP server. 2 ways of authenticating:
1. Obtain a higher privileged session key that has access to your account transactions, etc. :- You need to login with your GW2 client then obtain this session key either through fiddler or through other means (e.g. reading it off the GW2 client process memory or reading it off the GW2 browser cache).
2. Obtain a lower privileged session key by doing a HTTPS POST to https://account.guildwars2.com/login?redirect_uri=http%3A%2F%2Ftradingpost-live.ncplatform.net%2Fauthenticate%3Fsource%3D%252F&game_code=gw2 with the following parameters:
email = <your email address that you use to login to GW2>
password = <your password that you use to login to GW2>
Note that method 2 doesn’t require your GW2 client to be running and is useful for querying most of the data that you may need from the TP. I recommend using method 2 as your default means of authentication and only fall back to method 1 when you need to perform privileged transactions (e.g. create buy orders, cancel transactions, query current or past transactions, etc.) on your account.
Tonikor.5637:
What do I do when i get an “ERROR: Invalid authorization” message?
I’m asking this (and on an “old” post) because I used the tool a couple of days ago and it worked fine.
DarkSpirit.7046:
What do I do when i get an “ERROR: Invalid authorization” message?
I’m asking this (and on an “old” post) because I used the tool a couple of days ago and it worked fine.
Since it worked fine earlier, I suggest that you check the status of your account. Do a login at this URL and check your credentials:
Tonikor.5637:
works perfect now, thank you
DasPatAttack.2516:
1. Obtain a higher privileged session key that has access to your account transactions, etc. :- You need to login with your GW2 client then obtain this session key either through fiddler or through other means (e.g. reading it off the GW2 client process memory or reading it off the GW2 browser cache).
Awesome job guys.
I’m actually interested in knowing how to pass the higher privileged session key to connect and get my personal ackitten info.
I manage to get this session id, I’ll find my way fining the well formed url to get my specific user account transaction details but I’m missing the way to connect to your services using the higher privileged session key.
Could you help?
Thanks a bunch.
Ryan.9387:
The SessionID is included in most of the API requests you send. How I went about it was by using fiddler and copying the format of the requests sent by the game.
Go into the game with fiddler running and open something like “my buy orders.” The youcan minimize the game and look at the request that the game sent to the TP website. From there you simply have to copy the headers and values in your program’s html request.
Here is an example function from python that returns a list of your over cut WTBs. You can see where I pass the SessionID to the TPAPI.
import urllib
import urllib2
import json
def TPMyBuys(SessionID,count):
values = {"time" : “now”,“type” : “buy”,“charid” : "",“offset” : “1”,“count” : count}
data = urllib.urlencode(values)
req = urllib2.Request(“%s” %data)
req.add_header(“Accept” , “/”)
req.add_header(“Accept-Charset” , “iso-8859-1,*,utf-8”)
req.add_header( “Accept-Encoding” , “gzip;q=0”)
req.add_header(“Accept-Language” , “en”)
req.add_header(“Cookie” , SessionID) #<—————-
req.add_header( “User-Agent” , “Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1003.1 Safari/535.19 Awesomium/1.7.1”)
req.add_header(“Connection” , “keep-alive”)
req.add_header(“Host” , “tradingpost-live.ncplatform.net”)
req.add_header(“Referer” ,“https://tradingpost-live.ncplatform.net/me”)
req.add_header( “X-Requested-With” , “XMLHttpRequest”)
response = urllib2.urlopen(req)
parsed_json = json.loads(response.read())
return parsed_json
def TPMyBuysCheck(SessionID):
list = []
OBJ = TPMyBuys(SessionID,0)
OBJ = TPMyBuys(SessionID,str(OBJ[u’total’]))
for Item in OBJ[u’listings’]:
if int(Item[u’buy_price’]) > int(Item[u’unit_price’]):
list.append([str(Item[u’listing_id’]),str(Item[u’data_id’])])
return list
DasPatAttack.2516:
thanks a lot, going to try that ASAP.
Maximilian.1926:
regarding SessionID, how long is it active for after log-out from the game client? and is there a way to “refresh” it to keep it alive? or would something like that be a violation of the rules?
Ryan.9387:
I found it expires within 10 min or less. Constant use has no effect on it. It seems that you must have the client running to use the API.
Galowin.6089:
is it possible to extract ur bought/sold items lists (to datasheet)?
DarkSpirit.7046:
is it possible to extract ur bought/sold items lists (to datasheet)?
Yes you can do that programmatically.
In fact, I did that for my historical records of past items bought/sold, when I realized that I can do this to optimize my app.
My app saves a copy of my past items bought/sold in persistent memory. The next time I launch my app, it only downloads my past transactions up to the latest transactions stored in my persistent memory, saving on downloads, then does a merge of both the newer and older lists dynamically.
Maximilian.1926:
anyone know the difference between
https://tradingpost-live.ncplatform.net/ws/listings.json?id=##### and https://tradingpost-live.ncplatform.net/ws/me.json, encoding wise?
Im using python (urllisb2 and json) and I can read the me.json but I keep getting errors on the listings
DarkSpirit.7046:
me.json – gets your buy/sell/past buys/past sells transactions.
listings.json – gets the current buy and sell listings on an item.
me.json requires you to have the game client session key in your cookie when you communicate with the server. listing.json doesn’t need to and only requires the session key that you get by posting to “https://account.guildwars2.com/login?redirect_uri=http%3A%2F%2Ftradingpost-live.ncplatform.net%2Fauthenticate%3Fsource%3D%252F&game_code=gw2” with your login email and password. Therefore, listing.json does not require your guild wars 2 client to be running and logined while me.json does.
Maximilian.1926:
ok, I know about me.json needing the session key from the client, and I have that working, but I was tiring to use the same key with listings.json, could that be my problem?
I need to get both keys separately? I would think the client session key one should cover it as I can view that data in the client
DarkSpirit.7046:
ok, I know about me.json needing the session key from the client, and I have that working, but I was tiring to use the same key with listings.json, could that be my problem?
I need to get both keys separately? I would think the client session key one should cover it as I can view that data in the client
You do not need both keys if you already have the game client session key from your guild wars 2 client. That game client session key seems to have a higher privilege in the sense that it has access to more features of the web service (e.g. me.json) than the session key obtained from logging in to a web site. Therefore, if you have access to the game client session key, that is enough.
However, you have to keep your guild wars 2 client running in the background as the game client session key expires, if you log out, after a short while. The other session key lasts longer though and does not require your guild wars 2 client to be running.
Maximilian.1926:
ya that was my assumption,
I don’t know why im not able to decode the listing.json… I do get a response in my python program but then it fails at decoding it, while it works fine for me.json, (I have matched the hosts and header info for both requests according to what I get in fiddler from an in client action)
NVM
figured it out, I set accept-encoding to “gzip,q=0”, and now it seems to read it fine… although im now getting “gzip,deflate” from fideller…
DarkSpirit.7046:
ya that was my assumption,
I don’t know why im not able to decode the listing.json… I do get a response in my python program but then it fails at decoding it, while it works fine for me.json, (I have matched the hosts and header info for both requests according to what I get in fiddler from an in client action)NVM
figured it out, I set accept-encoding to “gzip,q=0”, and now it seems to read it fine… although im now getting “gzip,deflate” from fideller…
Setting gzip compression is usually a good idea. Although I have not written any python code before for that, I am sure you can easily search for how to uncompress the data in python.
It has been easy enough for me to handle gzip compression on my C# client.
Ryan.9387:
All you have to do is ask the API not to compress it in your headers. Read my posted code and note the gzip header. I get the json returned with that code.
DarkSpirit.7046:
All you have to do is ask the API not to compress it in your headers. Read my posted code and note the gzip header. I get the json returned with that code.
Then you are wasting bandwidth. Gzip reduces the time it takes for the website to transfer the data to your client. If you are not using it, then you are not being efficient.
If your client supports it, you should enable it, especially when it is so easy to uncompress the data.
http://love-python.blogspot.com/2008/07/accept-encoding-gzip-to-make-your.html
Ryan.9387:
That works too. I have no bandwidth issues though. Thank my uni internet for that. I may change my code later, but it remains fully functional at the moment.
Fossilized Amber.1352:
Question that I haven’t found to see in this thread I was directed to. How can you log into the TP and make api calls? I’ve used Fiddler and grabbed my session ID. I’m getting an access control origin error when I try to GET from the above-mentioned urls (to grab item data).
I am trying to keep this simple in JS/HTML, is this possible or do I need a server?
DarkSpirit.7046:
You need to be authenticated against their server in order to access the TP data. This will not allow you to access your own account as that would require a session key from the client itself.
Check this out:
Fossilized Amber.1352:
DarkSpirit, thanks for answering me, although my question isn’t exactly that. I have the session id and don’t know how to make api calls. I can re-direct to the page you linked to, but how can I make the api calls that I want to?
Threads? Server? I’m lost at this point.
I get access cross origin errors, because I am running a server (IIS from a c# project) – if that helps anybit
*Edit, I fixed my issue.
StevenL.3761:
If this is a C# project, then the usual way of dealing with this is to do all of the authentication and stuff on the server side in an ASP.NET Web API project. Your JS script should never need to call the TP service directly. Instead, it should call your own API controller. Your API controller should then take care of network handshakes and all that, then return the requested data from the TP service.
DarkSpirit.7046:
There 2 levels of session ids.
1. Level 1, you can get by sending your account information to https://account.guildwars2.com.
2. Level 2, gives you level 1 access + more privileges like accessing your own account. You can read it of process memory from your guild wars 2 client itself.
Check up the OP on accessing the TP
Fossilized Amber.1352:
Yes, thank you for clarifying what I wanted to say. How does an API controller work when talking to the TP? I can login but I am stuck on how to get my GET requests from the TP to my code. I am loading up the TP in an iframe and heard you can send messages to get around cross origin problems. Currently I can access the TP, change the URL and get my data; how can I program code to change the URL and get data?
Is there code I can see?
StevenL.3761:
Your JS script calls the API controller on your own server: http://yourserver/tradingpost/listings. This when your C# code takes over. Your API controller first ensures that your server has a valid session, then gets the requested data from the TP service. Returning the data to your script can be as simple as calling ‘Response.Write(json)’. This is when your JS script takes over again. It’s not particularly hard, and I think you’re overthinking this.
tl;dr: your API controller acts as a proxy that hides the complexity of maintaining a session
Dryalkiel.1385:
I’m getting the problems with listings.json as well. My Service had been running for months with no problems. Now listings.json doesn’t seem to work anymore. I tried it in my browser and it still throws an Access Denied response. search.json still works though.
Anyone aware of this issue?
DarkSpirit.7046:
I’m getting the problems with listings.json as well. My Service had been running for months with no problems. Now listings.json doesn’t seem to work anymore. I tried it in my browser and it still throws an Access Denied response. search.json still works though.
Anyone aware of this issue?
I think they made a change to listing.json to also require your game client session key. You can’t use the session key that you get from logging in to their web site.
As for an example with C# source code, you can look here:
Note: I am not Zicore and that is not my code. So, use it at your own risk.
Dryalkiel.1385:
Thanks… I tried this and unfortunately, the app cannot find my session key It just gives “squares” and some \0
Dryalkiel.1385:
The thing is, I AM able to get the sessionId from my application but when I use it to lookup search.json, it get a 401 error.
If I login with a browser and get the session Id from the cookie and skip the whole “GetSessionKey” part of my app, it works.
It’s like my session key expires as soon as I get it or something
DarkSpirit.7046:
The thing is, I AM able to get the sessionId from my application but when I use it to lookup search.json, it get a 401 error.
If I login with a browser and get the session Id from the cookie and skip the whole “GetSessionKey” part of my app, it works.
It’s like my session key expires as soon as I get it or something
You may have extracted the session key wrongly. Make sure the session key you got from the app. exactly matches the one showed in fiddler.
Dryalkiel.1385:
They can’t match since everytime you start a new session, you get a new one. I’ll mess around with it some more and if I find a solution I’ll post here.
Fossilized Amber.1352:
Your JS script calls the API controller on your own server: http://yourserver/tradingpost/listings. This when your C# code takes over. Your API controller first ensures that your server has a valid session, then gets the requested data from the TP service. Returning the data to your script can be as simple as calling ‘Response.Write(json)’. This is when your JS script takes over again. It’s not particularly hard, and I think you’re overthinking this.
tl;dr: your API controller acts as a proxy that hides the complexity of maintaining a session
Yes I might be, can I ask you again. Can you walk me through how to get “logged in” to the TP and then request some JSON data?
I have a controller action (MVC – asp.net) that has a cookie set (gotten from fiddler). What I don’t know how to do in asp.net, I don’t know if you can help me, is get my cookie from the server and start making requests so I can get json data. This is what I have so far:
public ActionResult GW2;
//myCookie.Expires = DateTime.Now.AddDays(1d);
//Response.Cookies.Add(myCookie);
Response.AddHeader(“s”, “XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX”);
Response.Redirect(“https://tradingpost-live.ncplatform.net/”);
return View();
}
*Edit, I just don’t know how to do this, I haven’t done this before.
Dryalkiel.1385:
Yay! Finally repaired it!
Basically, when you access the login page BEFORE login in, you get a session id in the cookies. You need to login with your email, password AND sessionId. this seems to “bind” the sessionid to your user. You also need to set the path and domain for your cookie → new Cookie(“s”, _SessionId, “/”, “guildwars2.com”);
@Fossilized Amber : You don’t want to use the sessionId from fiddler since everytime you login, you get a new sessionId. You’ll want to automate the “GetSessionKey” part of your application. You also don’t need to set the time the cookie expires. The response’s cookiecontainer will probably not return a Cookie object but you can retrieve it from Response.Headers[“Set-Cookie”].
DarkSpirit.7046:
Yay! Finally repaired it!
Basically, when you access the login page BEFORE login in, you get a session id in the cookies. You need to login with your email, password AND sessionId. this seems to “bind” the sessionid to your user. You also need to set the path and domain for your cookie -> new Cookie(“s”, _SessionId, “/”, “guildwars2.com”);
@Fossilized Amber : You don’t want to use the sessionId from fiddler since everytime you login, you get a new sessionId. You’ll want to automate the “GetSessionKey” part of your application. You also don’t need to set the time the cookie expires. The response’s cookiecontainer will probably not return a Cookie object but you can retrieve it from Response.Headers[“Set-Cookie”].
Like I have said, there are 2 levels of session ids. The one that you get from the website is the less useful form of session id because it would not allow you to buy items from the TP or see your own transactions. You may not even be able to use that to see the listings.json of each item.
The session id from the client would allow you to do all that and you can see that session id through fiddler when you open the TP dialog in the game.
They are BOTH set in the cookie of your requests. The session id usually remains valid for a long while.
Fossilized Amber.1352:
Email, password and session id. Besides finding a way to automate getting a session id from fiddler, if I am understanding this more, I need to have my email, password and session id on hand?
While I hate sounding like a broken record, Dryalkiel, can you explain what you mean by Response.Headers[“set-cookie”]? I don’t have enough experience to know what classes to use to do this. I was looking around at an HttpResponse class (something like that) in order to POST my information to the server (and bind this all to my user?). Should I be using a GET?
I understand this conceptually but not how to do it in code.
DarkSpirit.7046:
Email, password and session id. Besides finding a way to automate getting a session id from fiddler, if I am understanding this more, I need to have my email, password and session id on hand?
Once you have your session id, you don’t need your email and password anymore.
If you plan to get the less useful session id from the website, then you need to login using your email and password.
If you plan to get the more useful session id from the game client, you don’t need those. But you would probably need to write a program to access that session id.
Dryalkiel.1385:
That’s okay, the web sessionId is enough for me. My application just looks up prices. It doesn’t buy or sell so I don’t need the ingame key. Search.json does return a buy and sell price so I won’t need listings.json anymore. Thanks for the help though
@Fossilized Amber : Well, if you don’t have enough experience in this, isn’t this too big a project for you? At any rates, you might want to read up on a few things before diving in.
Here’s some useful links :
http://www.w3schools.com/tags/ref_httpmethods.asp
http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.aspx
http://msdn.microsoft.com/en-us/library/system.net.httpwebresponse.aspx
And no, not automate from FIDDLER. Fiddler is just a tool to lookup the info sent and obtained from your browser. You’ll want to automate the sessionId part from within your application by loging in with some HttpWebRequests.
You’ll want to lookup GW2Spidy too. It’s in PHP but the logic is basically the same.
Rand.3186:
It looks like they dropped the use of the “Character GUID.” When I run fiddler I no longer see the Character GUID being passed along with the session ID in the cookies section.
I looked into this because a program I made a few months ago was throwing an authorization error at me when I started it up today. It’s been a few weeks since I used it last.
The other change I noticed is that: tradingpost-live.ncplatform.net has been changed to: tradingpost-dfw-live.ncplatform.net.
DarkSpirit.7046:
That’s okay, the web sessionId is enough for me. My application just looks up prices. It doesn’t buy or sell so I don’t need the ingame key. Search.json does return a buy and sell price so I won’t need listings.json anymore. Thanks for the help though
That why I said it depends on what you need; the type of application that you want to write.
One thing to watch out for though, even if you are looking at the buy/sell price you have to be aware that there is a caching bug on the TP especially on fast moving items where the buy/sell price obtained from the TP (through search or items.json) is an outdated cached version. Listings.json does not have this problem and buy/sell price without quantity is limited for most usage. You only need 1 crazy buyer or seller to give you the wrong impression on the demand/supply of that item.
It looks like they dropped the use of the “Character GUID.” When I run fiddler I no longer see the Character GUID being passed along with the session ID in the cookies section.
I looked into this because a program I made a few months ago was throwing an authorization error at me when I started it up today. It’s been a few weeks since I used it last.
The other change I noticed is that: tradingpost-live.ncplatform.net has been changed to: tradingpost-dfw-live.ncplatform.net.
Just return an empty string now for character guid. You can still use tradingpost-live.
Rand.3186:
Just return an empty string now for character guid. You can still use tradingpost-live.
Yeah, that’s how I got around to fixing it. Wasn’t a problem once I realized what was changed. I only posted it so that anyone else bumping into the issue would know why.
One other thing I noticed around a month or so ago was that you more or less have to use listings.json now in order to be sure that you’re getting the current highest buy order / lowest sell price of an item.
Example: http://www.gw2spidy.com/item/20853 — Shows 99g. Cheapest is actually 9g. (This is not a fast moving item). This might only be an issue with relatively new items on the trading post? I haven’t quite figured out what the deal is with it. I think this might have been an intentional change to speed up the Trading Post; there was a patch a month or so ago that made the trading post much more responsive.
Fossilized Amber.1352:
Ok, I’ve made progress. Dryalkiel can you look at this?
I’ve used my session id from fiddler and I’m getting an “unauthorized” message back.
StevenL.3761:
Why are you setting UseCookies to false? Also, did you realize that you are never actually injecting your instance of HttpClientHandler into the HttpClient?
Line 35
UseCookies = true
Line 38
using (httpClient = new HttpClient(httpClientHandler) { BaseAddress = baseAddress })
Fossilized Amber.1352:
Of course! How did I not see that, thank you for your eagle-eyes StevenL.
I’ve got an updated pastebin here, it’s almost done. Another question I’m sending out, I am trying to save the HttpResponseMessage in a private variable in my class. The console doesn’t change output so this variable isn’t being correctly set. Any clue why that is?
*You can copy/paste the code as is (filling in the session id from fiddler) if you’d like to try it out yourself
FlacMatic.4258:
they changed something in their tradingpost link. can’t get it work anymore. and i’m too lazy right now to check for a new link
Pat Cavit.9234:
https://tradingpost-dfw-live.ncplatform.net
https://tradingpost-fra-live.ncplatform.net
You should really use the Official API though, we provide zero guarantees that we won’t break everything out from underneath you if you’re going against the TP directly.
ameerpostalman.8975:
Looks like this doesnt work anymore?
Pat Cavit.9234:
Looks like this doesnt work anymore?
TP was completely rewritten and all these endpoints are gone, yes.
You should really use the Official API though, we provide zero guarantees that we won’t break everything out from underneath you if you’re going against the TP directly.
Risingashes.8694:
Looks like this doesnt work anymore?
TP was completely rewritten and all these endpoints are gone, yes.
When was the TP completely rewritten? Because they only stopped working on 2nd Dec.
StevenL.3761:
Assuming that the original ncplatform APIs were reverse-engineered using web debugging proxies, what is stopping anybody from doing the same for the updated trading post?
darthmaim.6017:
When was the TP completely rewritten? Because they only stopped working on 2nd Dec.
https://www.guildwars2.com/en/news/introducing-the-new-trading-post/
Risingashes.8694:
When was the TP completely rewritten? Because they only stopped working on 2nd Dec.
https://www.guildwars2.com/en/news/introducing-the-new-trading-post/
Yes obviously the TP was rewritten at that point, yet the web endpoints were disabled this patch. Meaning the causal statement: The Trading Post was rewritten and as a result the web endpoints were broken- which @Pat Cavit seems to be suggesting doesn’t seem true.
If there were multiple rewritings that would make sense.
Pat Cavit.9234:
Sure, I see how what I said is confusing. I’ll elaborate.
As part of the rewrite we also set it up so that the Commerce apps could go over the existing game connection instead of making HTTP requests. It’s more efficient (there’s no per-host limit on the number of requests we can make) and avoids some of the overhead. Until we could do some more testing of that on live we had a simple HTTP proxy for requests.
Once we cut over completely to the game connection the HTTP proxy was automatically disabled. It’s been deleted entirely in dev so it will start 404ing before too long.
StevenL.3761:
Does that imply that we should get faster loading times now than back when the updated TP was launched?
Pat Cavit.9234:
Does that imply that we should get faster loading times now than back when the updated TP was launched?
Yeah, once the UI has loaded it’s noticeably faster searching/switching between sections/etc. We can avoid a lot of the TCP overhead of HTTP by re-using the existing game connection.
Len.1879:
So, is direct interaction with the TP still allowed though? I’d like to manage my transactions and especially add new ones while in university, where I can’t run GW2 on my netbook.
Pat Cavit.9234:
So, is direct interaction with the TP still allowed though? I’d like to manage my transactions and especially add new ones while in university, where I can’t run GW2 on my netbook.
Selling has always required a game client. Buying now requires a game client as well. Neither of those are likely to be exposed via the API any time soon.
Those restrictions could be worked around with a really convincing fake client, but I’m pretty sure that’s against our TOS.