Offical ruby client for the XING-API, providing easy access to all API endpoints and simplifies response parsing, error handling and tries to ease the oauth pain.
Ruby

README.md

Ruby client for the XING-API Build Status

XingAPI is the offical ruby client for the XING-API. It provides easy access to all API endpoints and simplifies response parsing, error handling and tries to ease the oauth pain. Before you can start using the client, you need a XING account and create an application in the developer portal to have a consumer_key and consumer_secret.

Installation

gem install xing_api

Getting started

The simplest way to do the oauth handshake and request your own user profile:

client = XingApi::Client.new consumer_key: "YOUR_CONSUMER_KEY", consumer_secret: "YOUR_CONSUMER_SECRET"
hash = client.get_request_token # => {:request_token=>"6479c262c06f4a002643", :request_token_secret=>"d7f5a128c01574e5bf10", :authorize_url=>"https://api.xing.com/v1/authorize?oauth_token=6479c262c06f4a002643"}
# open hash[:authorize_url] in your browser and authorize the access, remember the verifier, request_token and request_token_secret for the next step!
client.get_access_token("YOUR_VERIFIER", request_token:  "YOUR_REQUEST_TOKEN", request_token_secret: "YOUR_REQUEST_TOKEN_SECRET")
# ready to rock, but you have to supply the client instance with every call
XingApi::User.me(client: client)

If your know your oauth_token and oauth_token_secret already:

XingApi::Client.configure do |config|
  config.consumer_key = "YOUR_CONSUMER_KEY"
  config.consumer_secret = "YOUR_CONSUMER_SECRET"
  config.oauth_token = "THE_USERS_OAUTH_TOKEN"
  config.oauth_token_secret = "THE_USERS_OAUTH_TOKEN_SECRET"
end
# ready to rock, no need for a client instance to pass around
XingApi::User.me

Integrating it in a rails app

Outside of a console you problably want to use it a bit differently. So in a rails project for example, an initializer is a good place to put the consumer config:

XingApi::Client.configure do |config|
  config.consumer_key = "YOUR_CONSUMER_KEY"
  config.consumer_secret = "YOUR_CONSUMER_SECRET"
end

And, assuming you did the handshake for your user already and saved the result of Client#get_access_token together with your users id, you just need to create a client instance with the saved token and secret:

oauth_token, oauth_token_secret = # load from your db
client = XingApi::Client.new(oauth_token: oauth_token, oauth_token_secret: oauth_token_secret)

# ready to rock, there is no global token defined, so you have to supply the client instance
XingApi::User.me(client: client)

Or if you're code is executed single threaded anyway:

oauth_token, oauth_token_secret = # load from your db
XingApi::Client.configure do |config|
  config.oauth_token = oauth_token
  config.oauth_token_secret = oauth_token_secret
end

# no client instance needed, because oauth token is set globally
XingApi::User.me

Authenticate the user (a.k.a. the oauth handshake) is also simple, but you need to store the request_token and secret (temporarily) and the access_token and secret permanently (this token might work up to ten years), there is no need to do the handshake every time. At some point to need to start the process (assuming to configured the consumer_key and consumer_secret and your app is reachable via https://yoursite.com):

XingApi::Client.new.get_request_token("https://yoursite.com/xing_callback")
>> {:request_token=>"647...", :request_token_secret=>"d7f...", :authorize_url=>"https://api.xing.com/v1/authorize?oauth_token=647..."}

You need to store the request_token and the request_token_secret in your database and then redirect the user to the authorize_url, the user will leave your site and authorize on the xing.com. On the user granted access to your consumer, XING will redirect him back to

https://yoursite.com/xing_callback?oauth_token=647...&oauth_verifier=12345

Your app needs to get the access token next:

request_token, request_token_secret = # load from your db based on params[:oauth_token]
XingApi::Client.new.get_access_token(params[:oauth_verifier], request_token: request_token, request_token_secret: request_token_secret)
>> {:access_token=>"831...", :access_token_secret=>"d4a..."}

Store these in your database, and you're done.

Response headers

Besides of the response body that is returned you can also access the response headers:

response = XingApi::User.me
response[:users][0][:display_name]
>> "My Name"
response.headers["location"]
>> "https://api.xing.com/v1/some/location"

Error handling

Every API call might fail for a bunch of different reasons, some are call specific others might happen for every call. Every error case has a unique name, which you can use for specific error handling:

begin
  XingApi::User.me(fields: 'id,display_name,foobar')
rescue XingApi::Error => e
  e.status_code # 403
  e.name        # "INVALID_PARAMETERS"
  e.text        # "Invalid parameters (Invalid user field(s) given: foobar)"
  e.errors      # [{ field: 'some_field', reason: 'SOME_REASON' }]
end

There are some errors which your app should handle in any case:

  • XingApi::InvalidOauthTokenError (the token is not valid anymore, remove the entry from your db and start the handshake again)
  • XingApi::RateLimitExceededError (your consumer did too many request, try again later)
  • XingApi::ServerError (server side error)

Overview of all resources

Activities

  • XingApi::Activity.delete(activity_id, options = {}) (docs)
  • XingApi::Activity.find(activity_id, options = {}) (docs)
  • XingApi::Activity.share(activity_id, options = {}) (docs)
  • XingApi::Activity::Comment.list(activity_id, options = {}) (docs)
  • XingApi::Activity::Comment.create(activity_id, comment, options = {}) (docs)
  • XingApi::Activity::Comment.delete(activity_id, comment_id, options = {}) (docs)
  • XingApi::Activity::Like.list(activity_id, options = {}) (docs)
  • XingApi::Activity::Like.create(activity_id, options = {}) (docs)
  • XingApi::Activity::Like.delete(activity_id, options = {}) (docs)

Bookmarks

  • XingApi::Bookmark.create(user_id, options = {}) (docs)
  • XingApi::Bookmark.delete(user_id, options = {}) (docs)
  • XingApi::Bookmark.list(options = {}) (docs)

companies

  • XingApi::Company.find(company_id, options = {}) (docs)
  • XingApi::Company.search(keywords, options = {}) (docs)
  • XingApi::Company.unfollow(company_id, options = {}) (docs)
  • XingApi::Company.follow(company_id, options = {}) (docs)
  • XingApi::Company.employees(company_id, options = {}) (docs)
  • XingApi::Company.contacts(company_id, options = {}) (docs)
  • XingApi::Company::Update.list(company_id, options = {}) (docs)
  • XingApi::Company::Update.create(company_id, headline, content, options = {}) (docs)
  • XingApi::Company::Update.edit(update_id, options = {}) (docs)
  • XingApi::Company::Update.delete(update_id, options = {}) (docs)
  • XingApi::Company::Update.like(update_id, options = {}) (docs)
  • XingApi::Company::Update.unlike(update_id, options = {}) (docs)
  • XingApi::Company::Update::Comment.list(update_id, options = {}) (docs)
  • XingApi::Company::Update::Comment.create(update_id, content, options = {}) (docs)
  • XingApi::Company::Update::Comment.delete(update_id, comment_id, options = {}) (docs)

Contacts

  • XingApi::Contact.list(user_id, options = {}) (docs)
  • XingApi::Contact.list_ids(options = {}) (docs)
  • XingApi::Contact.shared(user_id, options = {}) (docs)
  • XingApi::Contact::Tag.list(user_id, options = {}) (docs)
  • XingApi::ContactRequest.accept(user_id, options = {}) (docs)
  • XingApi::ContactRequest.create(user_id, options = {}) (docs)
  • XingApi::ContactRequest.deny(user_id, options = {}) (docs)
  • XingApi::ContactRequest.list(options = {}) (docs)
  • XingApi::ContactRequest.sent(options = {}) (docs)

Messages

  • XingApi::Conversation.create(recipient_ids, subject, content, options = {}) (docs)
  • XingApi::Conversation.delete(conversation_id, options = {}) (docs)
  • XingApi::Conversation.find(conversation_id, options = {}) (docs)
  • XingApi::Conversation.list(options = {}) (docs)
  • XingApi::Conversation.read(conversation_id, options = {}) (docs)
  • XingApi::Conversation.unread(conversation_id, options = {}) (docs)
  • XingApi::Conversation.valid_recipient(recipient_id, options = {}) (docs)
  • XingApi::Conversation::Attachment.download_url(conversation_id, attachment_id, options = {}) (docs)
  • XingApi::Conversation::Attachment.list(conversation_id, options = {}) (docs)
  • XingApi::Conversation::Message.create(conversation_id, content, options = {}) (docs)
  • XingApi::Conversation::Message.find(conversation_id, message_id, options = {}) (docs)
  • XingApi::Conversation::Message.list(conversation_id, options = {}) (docs)
  • XingApi::Conversation::Message.read(conversation_id, message_id, options = {}) (docs)
  • XingApi::Conversation::Message.unread(conversation_id, message_id, options = {}) (docs)
  • XingApi::Invite.create(emails, options = {}) (docs)

Groups

  • XingApi::Group.list(user_id, options = {}) (docs)
  • XingApi::Group.search(keywords, options = {}) (docs)
  • XingApi::Group.read(group_id, options = {}) (docs)
  • XingApi::Group.join(group_id, options = {}) (docs)
  • XingApi::Group.leave(group_id, options = {}) (docs)
  • XingApi::Group::Forum.list(group_id, options = {}) (docs)
  • XingApi::Group::Forum::Post.create(forum_id, title, content, options = {}) (docs)
  • XingApi::Group::Forum::Post.list(forum_id, options = {}) (docs)
  • XingApi::Group::MediaPreview.create(url, options = {}) (docs)
  • XingApi::Group::Post.list(group_id, options = {}) (docs)
  • XingApi::Group::Post.find(post_id, options = {}) (docs)
  • XingApi::Group::Post.delete(post_id, options = {}) (docs)
  • XingApi::Group::Post::Comment.list(post_id, options = {}) (docs)
  • XingApi::Group::Post::Comment.create(post_id, content, options = {}) (docs)
  • XingApi::Group::Post::Comment.delete(comment_id, options = {}) (docs)
  • XingApi::Group::Post::Comment::Like.list(comment_id, options = {}) (docs)
  • XingApi::Group::Post::Comment::Like.create(comment_id, options = {}) (docs)
  • XingApi::Group::Post::Comment::Like.delete(comment_id, options = {}) (docs)
  • XingApi::Group::Post::Like.list(post_id, options = {}) (docs)
  • XingApi::Group::Post::Like.create(post_id, options = {}) (docs)
  • XingApi::Group::Post::Like.delete(post_id, options = {}) (docs)

Jobs

  • XingApi::Job.find(job_id, options = {}) (docs)
  • XingApi::Job.recommendations(options = {}) (docs)
  • XingApi::Job.search(query, options = {}) (docs)

News

  • XingApi::News::Article::Like.list(article_id, options = {}) (docs)
  • XingApi::News::Article::Like.create(article_id, options = {}) (docs)
  • XingApi::News::Article::Like.delete(article_id, options = {}) (docs)
  • XingApi::News::Article.find(article_id, options = {}) (docs)
  • XingApi::News::Article.update(article_id, version, options = {}) (docs)
  • XingApi::News::Article.delete(article_id, version, options = {}) (docs)
  • XingApi::News::Page.find(page_id, options = {}) (docs)
  • XingApi::News::Page.list_editable(options = {}) (docs)
  • XingApi::News::Page.list_following(options = {}) (docs)
  • XingApi::News::Page::Article.create(page_id, source_url, title, options = {}) (docs)
  • XingApi::News::Page::Article.list(page_id, options = {}) (docs)

Profile Messages

  • XingApi::ProfileMessage.delete(options = {}) (docs)
  • XingApi::ProfileMessage.find(user_id, options = {}) (docs)
  • XingApi::ProfileMessage.update(message, options = {}) (docs)

Visits

  • XingApi::ProfileVisit.create(user_id, options = {}) (docs)
  • XingApi::ProfileVisit.list(options = {}) (docs)

Users

  • XingApi::User.activities(user_id, options = {}) (docs)
  • XingApi::User.find(user_id, options = {}) (docs)
  • XingApi::User.find_by_emails(emails, options = {}) (docs)
  • XingApi::User.id_card(options = {}) (docs)
  • XingApi::User.me(options = {}) (docs)
  • XingApi::User.share_link(uri, options = {}) (docs)
  • XingApi::User.network_activities(options = {}) (docs)
  • XingApi::User.paths(user_id, options = {}) (docs)
  • XingApi::User.search(keywords, options = {}) (docs)
  • XingApi::User.shared(user_id, options = {}) (docs)
  • XingApi::User.status_message(message, options = {}) (docs)
  • XingApi::User.update(options = {}) (docs)
  • XingApi::User::BusinessAddress.update(options = {}) (docs)
  • XingApi::User::BirthDate.update(day, month, year, options = {}) (docs)
  • XingApi::User::Company.create(name, title, industry, employment_type, options = {}) (docs)
  • XingApi::User::Company.delete(company_id, options = {}) (docs)
  • XingApi::User::Company.primary_company(company_id, options = {}) (docs)
  • XingApi::User::Company.update(company_id, options = {}) (docs)
  • XingApi::User::Company.recommendations(options = {}) (docs)
  • XingApi::User::Company.following(options = {}) (docs)
  • XingApi::User::Company.managing(options = {}) (docs)
  • XingApi::User::Language.delete(language, options = {}) (docs)
  • XingApi::User::Language.update(language, options = {}) (docs)
  • XingApi::User::Photo.delete(options = {}) (docs)
  • XingApi::User::Photo.update(body_hash, options = {}) (docs)
  • XingApi::User::PrivateAddress.update(options = {}) (docs)
  • XingApi::User::Recommendation.delete(user_id, options = {}) (docs)
  • XingApi::User::Recommendation.list(options = {}) (docs)
  • XingApi::User::School.create(name, options = {}) (docs)
  • XingApi::User::School.delete(school_id, options = {}) (docs)
  • XingApi::User::School.update(school_id, options = {}) (docs)
  • XingApi::User::School.primary_school(school_id, options = {}) (docs)
  • XingApi::User::Qualification.create(description, options = {}) (docs)
  • XingApi::User::WebProfile.delete(profile, options = {}) (docs)

Contact

If you have problems or feedback, feel free to contact us:

If you want to contribute, just fork this project and send us a pull request.

Authors

Mark Schmidt and Johannes Strampe Please find out more about our work in our dev blog.

Copyright (c) 2016 XING AG

Released under the MIT license. For full details see LICENSE included in this distribution.