Alma REST API Ruby library
This is a simple Ruby library that acts as a wrapper for the Ex Libris Alma REST APIs.
The main purpose of this library is to abstract authentication, error handling, and response parsing.
It uses faraday as the underlying http client, nokogiri for XML parsing, and oj and hashie for JSON processing.
Note: This is NOT an official Alma API client. It is developed at the University Library of Paderborn as an open source project.
Installation
Add this to your Gemfile:
gem "alma_api"
and run the bundle install command in your terminal.
Usage
You need an API key for your Alma Instance in order to use this client. Please consult the Ex Libris developer documentation on how to use the Alma REST APIs for more information how to get and setup your API keys.
Creating a configuration
To use this library you need an AlmaApi::Client instance. The client requires an AlmaApi::Configuration.
configuration = AlmaApi::Configuration.new(
api_key: "...", # 1. required
base_url: "...", # 2. optional
default_format: "...", # 3. optional
language: "..." # 4. optional
)
api_keyAdd your Alma API key here.base_urlAdd the base URL to be used for each request. Ex Libris provides different API gateways for different geographical locations. See the documentation here for more information. This parameter is optional and defaults to the Alma API Gateway for Europe:https://api-eu.hosted.exlibrisgroup.com/almaws/v1.You can use a
Symbolas a shortcut to set thebase_urlfor one of the preconfigured gateways:na(North America),:eu(Europe),:ap(Asia-Pacific),:ca(Canada),:cn(China).For example, to set the
base_urlfor the canadian gateway, useconfiguration = AlmaApi::Configuration.new( base_url: :ca, ... )default_formatThe default format to use for each request. The client supportsjsonandxml. The default isjson.languageThe language used by Alma for error messages and textual information. The default is English (en). To change this, set this parameter to any 2-letter language code that is supported and enabled in Alma (see the mapping table "Institution Languages" in Alma).
Creating a client
With the configuration ready, you can create the client.
client = AlmaApi::Client.new(configuration)
As a shortcut, you can call AlmaApi.configure to get the client instance. Note that each call to AlmaApi.configure returns a new AlmaApi::Client instance.
client = AlmaApi.configure do |config|
api_key: "...",
base_url: "...",
default_format: "...",
language: "..."
end
Using the client
The client provides the following methods: #get, #post, #put and #delete to call the Alma APIs with the corresponding HTTP methods GET, POST, PUT and DELETE.
Each method expects a URL path to the resource relative to the configured base_url as it's first parameter. Parameters that the Alma API expects as part of the URL path must be included here.
To set query string parameters, set the params: option and provide a Ruby hash. To override the default_format for an individual request, you can set the format: option to json or xml, depending on your needs. Setting the format to xml is preferable for Alma APIs that work with MARCXML data.
To set the body of a #post or #put request, you can set the body: option. If the request format is json, the body: option should contain a valid json string. Otherwise, if the request format is xml, the option should be a valid XML string.
In the case of a json request, the result of the call is a Ruby hash. For xml, the result is a Nokogiri::XML::Document instance, as this library uses nokogiri under the hood for XML processing.
Examples
GET requests
Retrieve users
# Retrieve users (JSON)
users = client.get("users", params: {limit: 2})
# Retrieve users (XML)
users = client.get("users", params: {limit: 2}, format: :xml)
POST and PUT requests
Creating a user
# Prepare the data for a new user in Alma
user_data = {
record_type: {value: "PUBLIC"},
account_type: {value: "INTERNAL"},
preferred_language: {value: "de"},
status: {value: "ACTIVE"},
first_name: "FIRSTNAME",
last_name: "LASTNAME",
birth_date: "1978-07-07",
[...]
password: "SECRET PASSWORD",
force_password_change: true
}
# Create the user in Alma
user = client.post(
"users",
params: {
source_user_id: "xxx"
},
body: user_data.to_json
)
Updating a user
# First, get the user
user_id = "..." # a unique identifier for the user
user = client.get("users/#{user_id}") # user_id is a URL parameter
# Change the last name of the user
user["last_name"] = "..."
# Update the user in Alma
user = client.put("users/#{user_id}", body: user.to_json)
DELETE requests
Deleting a user
user_id = "..." # a unique identifier for the user
client.delete("users/#{user_id}") # user_id is a URL parameter
Error handling
There are three types of errors that can occur when calling the Alma APIs with this library. Each error exposes the #message and #code methods for further inspection. The message is returned in the language set in the configuration (default is English).
For gateway errors, the code is a string token (e.g. REQUEST_TOO_LARGE). For logical errors, the code is usually a number (e.g. 401850). See the "Possible Error Codes" section for each resource in the documentation for details.
1. AlmaApi::GatewayError
If the Alma API responds with a 4xx OR 5xx HTTP status AND one of the following error codes, an AlmaApi::GatewayError is thrown.
GENERAL_ERROR, UNAUTHORIZED, INVALID_REQUEST, PER_SECOND_THRESHOLD, DAILY_THRESHOLD, REQUEST_TOO_LARGE, FORBIDDEN, ROUTING_ERROR
Check the the documentation here for more information about gateway errors.
2. AlmaApi::ServerError
Any 5xx HTTP status that does not result in an AlmaApi::GatewayError will be thrown as an AlmaApi::ServerError.
3. AlmaApi::LogicalError
Any 4xx HTTP status that does not result in an AlmaApi::GatewayError will be thrown as an AlmaApi::LogicalError.
This is the most common error you will encounter and can be used to manage the control flow in your application.
For example, if you're loading a user's details, you don't want your application to blow up if a user with the specified user ID doesn't exist. Instead, you can handle the error like this:
def load_user(user_id)
client.get("users/#{user_id}")
rescue AlmaApi::LogicalError => e
# log the error
puts "Error #{e.code}: #{e.message}"
# ... the error code could be inspected and we could perform
# different things based on the error code but in this case
# we just return nil to indicate that the user does not exists.
nil
end
if (user = load_user("ALMA_USER_ID"))
puts "Hello #{user["first_name"]} #{user["last_name"]}"
else
puts "Too bad. No such user."
end