UPDATE 12/17/2013: The authentication process Yammer uses to issue an access code changed recently. If you have been getting a 404 error when executing the 3rd line of code previously described below to get the token, then read the updated step 3 below and/or grab the updated code attached to this post.
Recently I’ve been doing some work with the Yammer API from a console application. The Yammer API does not have ton of documentation right now, and what is there is primarily targeted at using the API from a browser-based application. But what about a classic scheduled task type application? For example, suppose you wanted to write an application that would go through once a day and post the current leaders in a sales contest you’re having. Imagine having your app read the data from SQL and then posting the information into the feed. There just isn’t a lot of details on using it from server side code, and virtually none using .NET so I figured I would share and spread the joy. Brian on the Yammer team was good enough to get me through a few of the rough spots so thank you Brian. I also am attaching my console app to this post so that you have sample code to see for yourself.
To begin with, you should take a look at http://developer.yammer.com. You’ll find the documentation there on the Yammer API and a sprinkling of samples throughout. The most important part of this process (assuming you have a Yammer network to work in already) is that you need to register a Yammer application. When you do that you will get a client ID and secret, and you will tell Yammer where token requests for your application should be returned. This process is explained in the Yammer developer documentation here: http://developer.yammer.com/introduction/#gs-registerapp.
Once you have your application registered you can start working on your code to call the Yammer APIs. The first thing you need in order to do anything useful is an access token. Obtaining an access token in Yammer is very much like getting an OAuth access token for a SharePoint App (and many other apps). If you’re in the browser, a user would get a prompt where they would be informed that your application would like to access their Yammer information, and the user can allow it or not. Once you get an access token it is good for a very, very, long time (“years” according to the Yammer documentation) so you don’t need to worry about doing this every time for every user – you can save your access token for a user and reuse it later.
This is important to remember, especially when you are just experimenting, because the Yammer documentation also describes how you can obtain an access token through the browser and then use that for your application. If you go to http://developer.yammer.com/authentication/, scroll down to the bottom of the page and read the section titled Generate a test access token for instructions on how to do this.
Now in my case, I didn’t want to go that route because I want something a little more hands off and sustainable. So what I did is go through the process once through the browser, trace everything with Fiddler, and then write some code to simulate a person going through that process. The flip side of taking this approach is that it does require you to have the credentials of the user you want to simulate granting the application rights to data, so neither option is really perfect. If you look at the code in my console app you go through this process to get an access token:
- Make a request to the oath endpoint in Yammer like this: https://www.yammer.com/dialog/oauth?client_id=” + CLIENT_ID + “&redirect_uri=” + REDIR_URL. In this case, “CLIENT_ID” is the client ID you got when you registered your app, and “REDIR_URL” is the Uri that the response from Yammer should return to when it’s finished. It’s important to remember that if you test on different machines or in different environments, if you change where the response is going back to you MUST go update your application configuration in Yammer. If your redirect_uri does not match the configuration of your application, then Yammer will just give you an error. When you do get a response, there’s an “authenticity” token that you’ll need to extract out of the body and use on your next request. Fortunately I’ve written wrapper code for making a request and extracting this token so it’s really just two lines of code: response = MakeGetRequest(permUrl); and then string authToken = GetAuthenticityToken(response);
- Next you’re going to take the authenticity token and do an HTTP POST back to Yammer along with the credentials for the user. When you do that there are also two cookies that you need to start sending along that were created when you made the first request: yamtrak_id and _workfeed_session_id. You’ll post that to https://www.yammer.com/session to create a session with Yammer. Again, I’ve wrapped up the POST and extracting and resubmitting the cookies so you are just making one method call: postResults = MakePostRequest(postBody, authUrl1).
- UPDATE: This process changes right here as of December 2013. Yammer has changed the authentication process, so here’s what we do on this step now: you just need to make the same exact request that you made in step 1, with one difference. When you make the request, you need to include the Yammer tracking ID and session ID cookie. I made this all very easy for you by just adding one additional optional parameter to the MakeGetRequest method – AddCookies. So to make this final request you just need one line of code: response = MakeGetRequest(permUrl, string.Empty, true); You should get an access code in the return query string just as you did with the previous code.
- Now that you have an access code you can make a request to https://www.yammer.com/oauth2/access_token.json?client_id=” + CLIENT_ID + “&client_secret=” + CLIENT_SECRET + “&code=” + accessCode. Just like before, “CLIENT_ID” and “CLIENT_SECRET” are what you got from Yammer when you registered your app; “accessCode” is the access code we got from step 3. If this works, you’ll get a whole bunch of JSON In return that includes information about the current user, as well as the access token that you’ll need to include in all of your subsequent requests to read or write data into Yammer.
Now things get a lot more fun. Since we’ll regularly be working with JSON when using the Yammer API, I’ve written a bunch of .NET classes that we can use to serialize and deserialize back and forth. For example, when you get the access token back you can create an instance of one of my classes with code like this: YammerAccessToken yat = YammerAccessToken.GetInstanceFromJson(response). Once you do that you can easily refer to all the JSON goo in a .NET world. So for example, to get the access token you can just refer to yat.TokenResponse.Token. That is in fact how you will pass your access token to all subsequent requests that require it.
Now let’s start playing with the data. Suppose you want to read the “All Messages” posts for a user? It becomes a pretty trivial piece of code:
//make the request to Yammer for messages
response = MakeGetRequest(“https://www.yammer.com/api/v1/messages.json”, yat.TokenResponse.Token);
//serialize the JSON that’s returned into one of Steve’s Yammer objects
YammerMessages yms = YammerMessages.GetInstanceFromJson(response);
//enumerate each message and do something
foreach (YammerMessage ym in yms.Messages)
{
Console.WriteLine(“Message: ” + ym.MessageContent.PlainText);
}
If you look at the class I created for messages you’ll see that you can get things like the message ID, sender ID, message type, sender type, Url, thread ID, language, plain text, rich text, attachments, likes, etc. All of these are simple to retrieve using this custom class.
Now suppose you just want to get information about a particular user? Again, two lines of code gets you there:
response = MakeGetRequest(currentUserUrl, yat.TokenResponse.Token);
YammerUser yu = YammerUser.GetInstanceFromJson(response);
Once you have the YammerUser you can get at things like name, department, job title, photo Url, contact information (like email), network settings, and the list of feeds and groups that they belong to. The last couple of items are important, because each feed and group contains an identifier, and you have to use that identifier when posting to it.
Posting a message to a feed is done via a FORM post, so we can again reuse some of the other code we’ve written. When you post a new message, Yammer actually returns a message collection back to you containing one message, and you can use the same method described above to serialize it into a class to view the results. Since this is just sample code, here’s an example of how I let the user running the console app just type in the message that they want posted to the newsfeed:
bool broadcastToAll = false;
Console.WriteLine(“Type in the message you want posted to the Yammer IT Group then press enter:”);
string myMessage = Console.ReadLine();
//it.GroupID is a group that I got for my user in one of the previous code samples
//the complete list of form variables that you can submit and their definition can
//be found at http://developer.yammer.com/restapi/ in the Manipulating
//Messages section
string msg = “body=” + myMessage + “&group_id=” + it.GroupID + “&broadcast=” + broadcastToAll.ToString();
//try adding the message
response = MakePostRequest(msg, (“https://www.yammer.com/api/v1/messages.json”, yat.TokenResponse.Token);
if (!string.IsNullOrEmpty(response))
{
YammerMessages newMsg = YammerMessages.GetInstanceFromJson(response);
Console.WriteLine(“message sent: ” + newMsg.Messages[0].MessageContent.PlainText);
}
Posting to a Yammer App page can be done using Yammer’s Open Graph API; they’ve documented it here: http://developer.yammer.com/opengraph/. You submit a multi-level chunk of JSON to create an entry using Open Graph, but again, I’ve created a custom object to make it easy for you. Here’s an example of using my object that wraps the JSON needed for Open Graph:
YammerGraphObject go = new YammerGraphObject();
go.Activity.Action = “create”;
go.Activity.Actor = new YammerActor(“Steve Peschka”, “speschka@www.northwinds.com”);
go.Activity.Message = “Hey can we finally get this crazy write stuff working??”;
go.Activity.Users.Add(new YammerActor(“Anne Wallace”, “annew@www.northwinds.com”));
go.Activity.Users.Add(new YammerActor(“Garth Fort”, “garthf@www.northwinds.com”));
YammerGraphObjectInstance jo = new YammerGraphObjectInstance();
jo.Url = “http://www.vbtoys.com”;
jo.Title = “yammo objectola”;
go.Activity.Object = jo;
//the key is really here – I’ve overridden the ToString() method to return a
//JSON payload that can be used with Yammer
string postData = go.ToString();
//now we can just post the data to Yammer to create it
response = MakePostRequest(postData, graphPostUrl, yat.TokenResponse.Token, “application/json”);
That pretty much wraps it up. This is far from an exhaustive list of things you can do with Yammer. What I wanted to do was just to give you a starting point of common tasks and data serialization techniques that you can use to build from. I think as you look into building with the Yammer API you will be able to use the sample application I’ve attached to this posting as a good starting point and pattern for creating whatever custom Yammer application you like. Now go get Yammered. 🙂
You can download the attachment here:
Thanks for your very informative article. I tried downloading the attachment “YammerDotNet.zip” from your OneDrive. But it contained the same contents as your “YammerCrawlSyncWithFileUpload.zip”. Can you validate? I am really interested in the code related to this particular article “Using the Yammer API in a .NET Client Application”
LikeLike
Hi Paul, the YammerCrawlSyncWithFileUpload is a superset of the code that’s in the Yammer API in a .NET Client Application. If you have either one, then you have all of the code that was in that original post attachment.
LikeLike
I downloaded your sample project and updated the ClientID,Secret,username,password and redirect url.But when running getting 404.My redirect url is mylocalhost:2020/home/auth
Please help
Thejus
LikeLike
Could you please suggest a correct redirect URL
LikeLike
See my other comments about this at https://samlman.wordpress.com/2015/03/02/some-more-advice-when-using-the-yammer-apis-with-net/.
LikeLike
Hi Thejus, see the updated advice on this; I don’t recommend trying to programmatically work through the consent process on Yammer. They periodically change that process and it’s very difficult to create a reliable long term solution. See here for more details: https://samlman.wordpress.com/2015/03/02/some-more-advice-when-using-the-yammer-apis-with-net/.
LikeLike
I was there to offer classes to a shopper. There’s a motive why they let PGA
pros play totally free there.
LikeLike
Just want to say your article is as astounding. The clarity in your post is just spectacular and i could assume
you’re an expert on this subject. Well with your permission let me to grab your feed to keep updated with forthcoming post.
Thanks a million and please keep up the gratifying work.
LikeLike
Thank you for the article and sample. We authenticate to Yammer using SAML 2 (through Okta) and the MakeRequest method is returning the “The remote server returned an error: (404) Not Found.” error (have the current sample as of today).
Should this still work with SSO?
LikeLike
As Yammer people have changed their API.Please add
const string LOGIN_CSRF_TOKEN_COOKIE = “login_csrf_token”; inside SetCookies method.
LikeLike
Hi it’s me, I am also visiting this web page daily, this web site is really good and
the people are truly sharing nice thoughts.
LikeLike
Hi – I am following the code sample shared above, however getting access token as blank. Could you please suggest what could be issue in this case.
LikeLike
Tanks for this post. I have read this post and try to implement for yammer integration but I am not able to get the code which return from postResults = MakePostRequest(postBody, authUrl2); method and redirect to https://www.yammer.com/conteches.com/dialog/authenticate?client_id=XXX URL. Is there anything which I am missing to authenticate with yammer?
LikeLike
[…] For custom HttpRequest, I’ve used code from this blog post. […]
LikeLike
[…] MakeGetRequest and MakePostRequest from this excellent blog post. AuthenticationHelper reuses code created in my earlier blog […]
LikeLike
You actually make it appear so easy along with your presentation however I find this matter
to be really one thing which I believe I’d by no means understand.
It seems too complex and very vast for me. I’m having a look ahead to your subsequent post,
I will attempt to get the cling of it!
LikeLike
Hi,
How can we get all the Feeds using your App using the Embed Feature of Yammer.
Thanks
Dipak
LikeLike
Hi ,
how can I do authentication in console application before retiring the posts
LikeLike
Thanks for finally writing about >Using the Yammer API in a .NET Client Application | Share-n-Dipity <Liked it!
LikeLike
[…] MakeGetRequest and MakePostRequest from this excellent blog post. AuthenticationHelper reuses code created in my earlier blog […]
LikeLike
[…] or effect anyway. there redirects, i’m supposed have redirecturi yammer direct me… so other example – other illustration of using .net sdk […]
LikeLike
Hi, i think that i noticed you visited my site thus i got here to go back the prefer?.I am trying to to find things to
enhance my web site!I suppose its good enough to use a few of
your ideas!!
LikeLike
Hi friends, its great article about cultureand completely defined,
keep it up all the time.
LikeLike
Hi,
I need to use yammer api to include yammer chat in my application. I am not able to find one. Plz help me with it
LikeLike
hi I am not able to generate access_token using your code
response = MakeGetRequest(permUrl, string.Empty, true); this is coming empty for me
qsCode = wResp.ResponseUri.Query;
this line is giving me client_id in return. Please help me with this.
LikeLike
Hei Heidi;)Takk for koselige ord om pi;trommeek)Men det var nok feil dame du svarte ang julebordet i går;))Den skulle nok til en annen, for jeg hang hjemme med en snuppe med omgangssyke, ingen fest på meg:)Klem Line
LikeLike
Hello
I have tried to use your code for testing purpose and it is working fine when i am inputting access token but i tried to get access token at run time using steps as you have explained above and in code that is not working
at this line
if (qsCode.IndexOf(“code”) > -1)
i am not getting code response and due to empty access token all code breaks and noting works next.
Please help
Regards,
Ahmad Sumraiz
sumraizrana@gmail.com
LikeLike