diff --git a/config/vufind/Folio.ini b/config/vufind/Folio.ini
new file mode 100644
index 0000000000000000000000000000000000000000..94dadbd80867a68b97d248d48ecff1e45945cb24
--- /dev/null
+++ b/config/vufind/Folio.ini
@@ -0,0 +1,4 @@
+[Folio]
+base_url = https://localhost:9130
+username = diku_admin
+password = admin
diff --git a/module/VuFind/src/VuFind/ILS/Driver/AbstractAPI.php b/module/VuFind/src/VuFind/ILS/Driver/AbstractAPI.php
new file mode 100644
index 0000000000000000000000000000000000000000..65811acf2c97cc35da63fc7c1f5d7b1d7caa8c05
--- /dev/null
+++ b/module/VuFind/src/VuFind/ILS/Driver/AbstractAPI.php
@@ -0,0 +1,134 @@
+<?php
+/**
+ * Abstract Driver for API-based ILS drivers
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2018.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @category VuFind
+ * @package  ILS_Drivers
+ * @author   Chris Hallberg <challber@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:ils_drivers Wiki
+ */
+namespace VuFind\ILS\Driver;
+
+use VuFind\Exception\BadRequest as BadRequest;
+use VuFind\Exception\Forbidden as Forbidden;
+use VuFind\Exception\ILS as ILSException;
+use VuFind\Exception\RecordMissing as RecordMissing;
+use VuFindHttp\HttpServiceAwareInterface;
+use Zend\Log\LoggerAwareInterface;
+
+/**
+ * Abstract Driver for API-based ILS drivers
+ *
+ * @category VuFind
+ * @package  ILS_Drivers
+ * @author   Chris Hallberg <challber@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:ils_drivers Wiki
+ */
+abstract class AbstractAPI extends AbstractBase implements HttpServiceAwareInterface,
+    LoggerAwareInterface
+{
+    use \VuFind\Log\LoggerAwareTrait {
+        logError as error;
+    }
+    use \VuFindHttp\HttpServiceAwareTrait;
+
+    /**
+     * Allow default corrections to all requests
+     *
+     * @param \Zend\Http\Headers $headers the request headers
+     * @param array              $params  the parameters object
+     *
+     * @return array
+     */
+    protected function preRequest(\Zend\Http\Headers $headers, $params)
+    {
+        return [$headers, $params];
+    }
+
+    /**
+     * Make requests
+     *
+     * @param string $method  GET/POST/PUT/DELETE/etc
+     * @param string $path    API path (with a leading /)
+     * @param array  $params  Parameters object to be sent as data
+     * @param array  $headers Additional headers
+     *
+     * @return \Zend\Http\Response
+     */
+    public function makeRequest($method = "GET", $path = "/", $params = [],
+        $headers = []
+    ) {
+        $client = $this->httpService->createClient(
+            $this->config['API']['base_url'] . $path,
+            $method,
+            120
+        );
+        // error_log($method . ' ' . $this->config['API']['base_url'] . $path);
+
+        // Add default headers and parameters
+        $req_headers = $client->getRequest()->getHeaders();
+        $req_headers->addHeaders($headers);
+        list($req_headers, $params) = $this->preRequest($req_headers, $params);
+
+        // Add params
+        if ($method == 'GET') {
+            $client->setParameterGet($params);
+        } else {
+            if (is_string($params)) {
+                $client->getRequest()->setContent($params);
+            } else {
+                $client->setParameterPost($params);
+            }
+        }
+        $response = $client->send();
+        switch ($response->getStatusCode()) {
+        case 400:
+            throw new BadRequest($response->getBody());
+        case 401:
+        case 403:
+            throw new Forbidden($response->getBody());
+        case 404:
+            throw new RecordMissing($response->getBody());
+        case 500:
+            throw new ILSException("500: Internal Server Error");
+        }
+        return $response;
+    }
+
+    /**
+     * Set the configuration for the driver.
+     *
+     * @param array $config Configuration array (usually loaded from a VuFind .ini
+     * file whose name corresponds with the driver class name).
+     *
+     * @throws ILSException if base url excluded
+     * @return void
+     */
+    public function setConfig($config)
+    {
+        parent::setConfig($config);
+        // Base URL required for API drivers
+        if (!isset($config['API']['base_url'])) {
+            throw new ILSException('API Driver configured without base url.');
+        }
+    }
+}
diff --git a/module/VuFind/src/VuFind/ILS/Driver/Folio.php b/module/VuFind/src/VuFind/ILS/Driver/Folio.php
new file mode 100644
index 0000000000000000000000000000000000000000..356334a88d88f2e14f04d2fe5fe4b18ba435caef
--- /dev/null
+++ b/module/VuFind/src/VuFind/ILS/Driver/Folio.php
@@ -0,0 +1,803 @@
+<?php
+/**
+ * FOLIO REST API driver
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2018.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @category VuFind
+ * @package  ILS_Drivers
+ * @author   Chris Hallberg <challber@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:ils_drivers Wiki
+ */
+namespace VuFind\ILS\Driver;
+
+use VuFind\Exception\ILS as ILSException;
+use VuFind\I18n\Translator\TranslatorAwareInterface;
+use VuFindHttp\HttpServiceAwareInterface as HttpServiceAwareInterface;
+
+/**
+ * FOLIO REST API driver
+ *
+ * @category VuFind
+ * @package  ILS_Drivers
+ * @author   Chris Hallberg <challber@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:ils_drivers Wiki
+ */
+class Folio extends AbstractAPI implements
+    HttpServiceAwareInterface, TranslatorAwareInterface
+{
+    use \VuFindHttp\HttpServiceAwareTrait;
+    use \VuFind\I18n\Translator\TranslatorAwareTrait;
+
+    /**
+     * Authentication tenant (X-Okapi-Tenant)
+     *
+     * @var string
+     */
+    protected $tenant = null;
+
+    /**
+     * Authentication token (X-Okapi-Token)
+     *
+     * @var string
+     */
+    protected $token = null;
+
+    /**
+     * Factory function for constructing the SessionContainer.
+     *
+     * @var Callable
+     */
+    protected $sessionFactory;
+
+    /**
+     * Session cache
+     *
+     * @var \Zend\Session\Container
+     */
+    protected $sessionCache;
+
+    /**
+     * Constructor
+     *
+     * @param \VuFind\Date\Converter $dateConverter  Date converter object
+     * @param Callable               $sessionFactory Factory function returning
+     * SessionContainer object
+     */
+    public function __construct(\VuFind\Date\Converter $dateConverter,
+        $sessionFactory
+    ) {
+        $this->dateConverter = $dateConverter;
+        $this->sessionFactory = $sessionFactory;
+    }
+
+    /**
+     * Set the configuration for the driver.
+     *
+     * @param array $config Configuration array (usually loaded from a VuFind .ini
+     * file whose name corresponds with the driver class name).
+     *
+     * @throws ILSException if base url excluded
+     * @return void
+     */
+    public function setConfig($config)
+    {
+        parent::setConfig($config);
+        $this->tenant = $this->config['API']['tenant'];
+    }
+
+    /**
+     * (From AbstractAPI) Allow default corrections to all requests
+     *
+     * Add X-Okapi headers and Content-Type to every request
+     *
+     * @param \Zend\Http\Headers $headers the request headers
+     * @param object             $params  the parameters object
+     *
+     * @return array
+     */
+    public function preRequest(\Zend\Http\Headers $headers, $params)
+    {
+        $headers->addHeaderLine('Accept', 'application/json');
+        if (!$headers->has('Content-Type')) {
+            $headers->addHeaderLine('Content-Type', 'application/json');
+        }
+        $headers->addHeaderLine('X-Okapi-Tenant', $this->tenant);
+        if ($this->token != null) {
+            $headers->addHeaderLine('X-Okapi-Token', $this->token);
+        }
+        return [$headers, $params];
+    }
+
+    /**
+     * Login and receive a new token
+     *
+     * @return void
+     */
+    protected function renewTenantToken()
+    {
+        $this->token = null;
+        $auth = [
+            'username' => $this->config['API']['username'],
+            'password' => $this->config['API']['password'],
+        ];
+        $response = $this->makeRequest('POST', '/authn/login', json_encode($auth));
+        if ($response->getStatusCode() >= 400) {
+            throw new ILSException($response->getBody());
+        }
+        $this->token = $response->getHeaders()->get('X-Okapi-Token')
+            ->getFieldValue();
+        $this->sessionCache->folio_token = $this->token;
+    }
+
+    /**
+     * Check if our token is still valid
+     *
+     * Method taken from Stripes JS (loginServices.js:validateUser)
+     *
+     * @return void
+     */
+    protected function checkTenantToken()
+    {
+        $response = $this->makeRequest('GET', '/users');
+        if ($response->getStatusCode() >= 400) {
+            $this->token = null;
+            $this->renewTenantToken();
+        }
+    }
+
+    /**
+     * Initialize the driver.
+     *
+     * Check or renew our auth token
+     *
+     * @return void
+     */
+    public function init()
+    {
+        $factory = $this->sessionFactory;
+        $this->sessionCache = $factory($this->tenant);
+        if ($this->sessionCache->folio_token ?? false) {
+            $this->token = $this->sessionCache->folio_token;
+        }
+        if ($this->token == null) {
+            $this->renewTenantToken();
+        } else {
+            $this->checkTenantToken();
+        }
+    }
+
+    /**
+     * Get local bib id from inventory by following parents up the tree
+     *
+     * @param string $instanceId Instance-level id (lowest level)
+     * @param string $holdingId  Holding-level id (looked up from instance if null)
+     * @param string $itemId     Item-level id (looked up from holding if null)
+     *
+     * @return string Local bib id retrieved from Folio identifiers
+     */
+    protected function getBibId($instanceId, $holdingId = null, $itemId = null)
+    {
+        if ($instanceId == null) {
+            if ($holdingId == null) {
+                $response = $this->makeRequest(
+                    'GET',
+                    '/item-storage/items/' . $itemId
+                );
+                $item = json_decode($response->getBody());
+                $holdingId = $item->holdingsRecordId;
+            }
+            $response = $this->makeRequest(
+                'GET', '/holdings-storage/holdings/' . $holdingId
+            );
+            $holding = json_decode($response->getBody());
+            $instanceId = $holding->instanceId;
+        }
+        $response = $this->makeRequest(
+            'GET', '/inventory/instances/' . $instanceId
+        );
+        $instance = json_decode($response->getBody());
+        return $instance->identifiers[0]->value;
+    }
+
+    /**
+     * Get raw object of item from inventory/items/
+     *
+     * @param string $bibId Bib-level id
+     *
+     * @throw
+     * @return array
+     */
+    protected function getInstance($bibId)
+    {
+        $escaped = str_replace('"', '\"', str_replace('&', '%26', $bibId));
+        $query = [
+            'query' => '(id="' . $escaped . '" or identifiers="' . $escaped . '")'
+        ];
+        $response = $this->makeRequest('GET', '/instance-storage/instances', $query);
+        $instances = json_decode($response->getBody());
+        if (count($instances->instances) == 0) {
+            throw new ILSException("Item Not Found");
+        }
+        return $instances->instances[0];
+    }
+
+    /**
+     * Get raw object of item from inventory/items/
+     *
+     * @param string $itemId Item-level id
+     *
+     * @return array
+     */
+    public function getStatus($itemId)
+    {
+        return $this->getHolding($itemId);
+    }
+
+    /**
+     * This method calls getStatus for an array of records or implement a bulk method
+     *
+     * @param array $idList Item-level ids
+     *
+     * @return array values from getStatus
+     */
+    public function getStatuses($idList)
+    {
+        $status = [];
+        foreach ($idList as $id) {
+            $status[] = $this->getStatus($id);
+        }
+        return $status;
+    }
+
+    /**
+     * Retrieves renew, hold and cancel settings from the driver ini file.
+     *
+     * @param string $function The name of the feature to be checked
+     * @param array  $params   Optional feature-specific parameters (array)
+     *
+     * @return array An array with key-value pairs.
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
+    public function getConfig($function, $params = null)
+    {
+        return $this->config[$function] ?? false;
+    }
+
+    /**
+     * This method queries the ILS for holding information.
+     *
+     * @param string $bibId  Bib-level id
+     * @param array  $patron Patron login information from $this->patronLogin
+     *
+     * @return array An array of associative holding arrays
+     */
+    public function getHolding($bibId, array $patron = null)
+    {
+        $instance = $this->getInstance($bibId);
+        $query = ['query' => '(instanceId="' . $instance->id . '")'];
+        $holdingResponse = $this->makeRequest(
+            'GET',
+            '/holdings-storage/holdings',
+            $query
+        );
+        $holdingBody = json_decode($holdingResponse->getBody());
+        $items = [];
+        for ($i = 0; $i < count($holdingBody->holdingsRecords); $i++) {
+            $holding = $holdingBody->holdingsRecords[$i];
+            $locationName = '';
+            if (!empty($holding->permanentLocationId)) {
+                $locationResponse = $this->makeRequest(
+                    'GET',
+                    '/locations/' . $holding->permanentLocationId
+                );
+                $location = json_decode($locationResponse->getBody());
+                $locationName = $location->name;
+            }
+
+            $query = ['query' => '(holdingsRecordId="' . $holding->id . '")'];
+            $itemResponse = $this->makeRequest('GET', '/item-storage/items', $query);
+            $itemBody = json_decode($itemResponse->getBody());
+            for ($j = 0; $j < count($itemBody->items); $j++) {
+                $item = $itemBody->items[$j];
+                $items[] = [
+                    'id' => $bibId,
+                    'item_id' => $instance->id,
+                    'holding_id' => $holding->id,
+                    'number' => count($items),
+                    'barcode' => $item->barcode ?? '',
+                    'status' => $item->status->name,
+                    'availability' => $item->status->name == 'Available',
+                    'notes' => $item->notes ?? [],
+                    'callnumber' => $holding->callNumber,
+                    'location' => $locationName,
+                    'reserve' => 'TODO',
+                    'addLink' => true
+                ];
+            }
+        }
+        return $items;
+    }
+
+    /**
+     * Patron Login
+     *
+     * This is responsible for authenticating a patron against the catalog.
+     *
+     * @param string $username The patron username
+     * @param string $password The patron password
+     *
+     * @return mixed Associative array of patron info on successful login,
+     *               null on unsuccessful login.
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
+    public function patronLogin($username, $password)
+    {
+        // Get user id
+        $query = ['query' => 'username == ' . $username];
+        $response = $this->makeRequest('GET', '/users', $query);
+        $json = json_decode($response->getBody());
+        if (count($json->users) == 0) {
+            throw new ILSException("User not found");
+        }
+        $profile = $json->users[0];
+        $credentials = [
+            'userId' => $profile->id,
+            'username' => $username,
+            'password' => $password,
+        ];
+        // Get token
+        try {
+            $response = $this->makeRequest(
+                'POST',
+                '/authn/login',
+                json_encode($credentials)
+            );
+            // Replace admin with user as tenant
+            $this->token = $response->getHeaders()->get('X-Okapi-Token')
+                ->getFieldValue();
+            return [
+                'id' => $profile->id,
+                'username' => $username,
+                'cat_username' => $username,
+                'cat_password' => $password,
+                'firstname' => $profile->personal->firstName ?? null,
+                'lastname' => $profile->personal->lastName ?? null,
+                'email' => $profile->personal->email ?? null,
+            ];
+        } catch (Exception $e) {
+            return null;
+        }
+    }
+
+    /**
+     * This method queries the ILS for a patron's current profile information
+     *
+     * @param array $patron Patron login information from $this->patronLogin
+     *
+     * @return array Profile data in associative array
+     */
+    public function getMyProfile($patron)
+    {
+        $query = ['query' => 'username == "' . $patron['username'] . '"'];
+        $response = $this->makeRequest('GET', '/users', $query);
+        $users = json_decode($response->getBody());
+        $profile = $users->users[0];
+        return [
+            'id' => $profile->id,
+            'firstname' => $profile->personal->firstName ?? null,
+            'lastname' => $profile->personal->lastName ?? null,
+            'address1' => $profile->personal->addresses[0]->addressLine1 ?? null,
+            'city' => $profile->personal->addresses[0]->city ?? null,
+            'country' => $profile->personal->addresses[0]->countryId ?? null,
+            'zip' => $profile->personal->addresses[0]->postalCode ?? null,
+            'phone' => $profile->personal->phone ?? null,
+            'mobile_phone' => $profile->personal->mobilePhone ?? null,
+            'expiration_date' => $profile->expirationDate ?? null,
+        ];
+    }
+
+    /**
+     * This method queries the ILS for a patron's current checked out items
+     *
+     * Input: Patron array returned by patronLogin method
+     * Output: Returns an array of associative arrays.
+     *         Each associative array contains these keys:
+     *         duedate - The item's due date (a string).
+     *         dueTime - The item's due time (a string, optional).
+     *         dueStatus - A special status – may be 'due' (for items due very soon)
+     *                     or 'overdue' (for overdue items). (optional).
+     *         id - The bibliographic ID of the checked out item.
+     *         source - The search backend from which the record may be retrieved
+     *                  (optional - defaults to Solr). Introduced in VuFind 2.4.
+     *         barcode - The barcode of the item (optional).
+     *         renew - The number of times the item has been renewed (optional).
+     *         renewLimit - The maximum number of renewals allowed
+     *                      (optional - introduced in VuFind 2.3).
+     *         request - The number of pending requests for the item (optional).
+     *         volume – The volume number of the item (optional).
+     *         publication_year – The publication year of the item (optional).
+     *         renewable – Whether or not an item is renewable
+     *                     (required for renewals).
+     *         message – A message regarding the item (optional).
+     *         title - The title of the item (optional – only used if the record
+     *                                        cannot be found in VuFind's index).
+     *         item_id - this is used to match up renew responses and must match
+     *                   the item_id in the renew response.
+     *         institution_name - Display name of the institution that owns the item.
+     *         isbn - An ISBN for use in cover image loading
+     *                (optional – introduced in release 2.3)
+     *         issn - An ISSN for use in cover image loading
+     *                (optional – introduced in release 2.3)
+     *         oclc - An OCLC number for use in cover image loading
+     *                (optional – introduced in release 2.3)
+     *         upc - A UPC for use in cover image loading
+     *               (optional – introduced in release 2.3)
+     *         borrowingLocation - A string describing the location where the item
+     *                         was checked out (optional – introduced in release 2.4)
+     *
+     * @param array $patron Patron login information from $this->patronLogin
+     *
+     * @return array Transactions associative arrays
+     */
+    public function getMyTransactions($patron)
+    {
+        $query = ['query' => 'userId==' . $patron['username']];
+        $response = $this->makeRequest("GET", '/circulation/loans', $query);
+        $json = json_decode($response->getBody());
+        if (count($json->loans) == 0) {
+            return [];
+        }
+        $transactions = [];
+        foreach ($json->loans as $trans) {
+            $dueDate = date_create($trans['dueDate']);
+            $transactions[] = [
+                'duedate' => date_format($date, "j M Y"),
+                'dueTime' => date_format($date, "g:i:s a"),
+                // TODO: Due Status
+                // 'dueStatus' => $trans['itemId'],
+                'id' => $trans['itemId'],
+                'barcode' => $trans['item']['barcode'],
+                'title' => $trans['item']['title'],
+            ];
+        }
+        return $transactions;
+    }
+
+    /**
+     * Get Pick Up Locations
+     *
+     * This is responsible get a list of valid locations for holds / recall
+     * retrieval
+     *
+     * @param array $patron Patron information returned by $this->patronLogin
+     *
+     * @return array An array of associative arrays with locationID and
+     * locationDisplay keys
+     */
+    public function getPickupLocations($patron)
+    {
+        $response = $this->makeRequest('GET', '/locations');
+        $json = json_decode($response->getBody());
+        $locations = [];
+        foreach ($json->locations as $location) {
+            $locations[] = [
+                'locationID' => $location->id,
+                'locationDisplay' => $location->name
+            ];
+        }
+        return $locations;
+    }
+
+    /**
+     * This method queries the ILS for a patron's current holds
+     *
+     * Input: Patron array returned by patronLogin method
+     * Output: Returns an array of associative arrays, one for each hold associated
+     * with the specified account. Each associative array contains these keys:
+     *     type - A string describing the type of hold – i.e. hold vs. recall
+     * (optional).
+     *     id - The bibliographic record ID associated with the hold (optional).
+     *     source - The search backend from which the record may be retrieved
+     * (optional - defaults to Solr). Introduced in VuFind 2.4.
+     *     location - A string describing the pickup location for the held item
+     * (optional). In VuFind 1.2, this should correspond with a locationID value from
+     * getPickUpLocations. In VuFind 1.3 and later, it may be either
+     * a locationID value or a raw ready-to-display string.
+     *     reqnum - A control number for the request (optional).
+     *     expire - The expiration date of the hold (a string).
+     *     create - The creation date of the hold (a string).
+     *     position – The position of the user in the holds queue (optional)
+     *     available – Whether or not the hold is available (true/false) (optional)
+     *     item_id – The item id the request item (optional).
+     *     volume – The volume number of the item (optional)
+     *     publication_year – The publication year of the item (optional)
+     *     title - The title of the item
+     * (optional – only used if the record cannot be found in VuFind's index).
+     *     isbn - An ISBN for use in cover image loading (optional)
+     *     issn - An ISSN for use in cover image loading (optional)
+     *     oclc - An OCLC number for use in cover image loading (optional)
+     *     upc - A UPC for use in cover image loading (optional)
+     *     cancel_details - The cancel token, or a blank string if cancel is illegal
+     * for this hold; if omitted, this will be dynamically generated using
+     * getCancelHoldDetails(). You should only fill this in if it is more efficient
+     * to calculate the value up front; if it is an expensive calculation, you should
+     * omit the value entirely and let getCancelHoldDetails() do its job on demand.
+     * This optional feature was introduced in release 3.1.
+     *
+     * @param array $patron Patron login information from $this->patronLogin
+     *
+     * @return array Associative array of holds information
+     */
+    public function getMyHolds($patron)
+    {
+        // Get user id
+        $query = ['query' => 'username == "' . $patron['username'] . '"'];
+        $response = $this->makeRequest('GET', '/users', $query);
+        $users = json_decode($response->getBody());
+        $query = [
+            'query' => 'requesterId == "' . $users->users[0]->id . '"' .
+                ' and requestType == "Hold"'
+        ];
+        // Request HOLDS
+        $response = $this->makeRequest('GET', '/request-storage/requests', $query);
+        $json = json_decode($response->getBody());
+        $holds = [];
+        foreach ($json->requests as $hold) {
+            $holds[] = [
+                'type' => 'Hold',
+                'create' => $hold->requestDate,
+                'expire' => $hold->requestExpirationDate,
+                'id' => $this->getBibId(null, null, $hold->itemId),
+            ];
+        }
+        return $holds;
+    }
+
+    /**
+     * Place Hold
+     *
+     * Attempts to place a hold or recall on a particular item and returns
+     * an array with result details.
+     *
+     * @param array $holdDetails An array of item and patron data
+     *
+     * @return mixed An array of data on the request including
+     * whether or not it was successful and a system message (if available)
+     */
+    public function placeHold($holdDetails)
+    {
+        try {
+            $requiredBy = date_create_from_format(
+                'm-d-Y',
+                $holdDetails['requiredBy']
+            );
+        } catch (Exception $e) {
+            throw new ILSException('hold_date_invalid');
+        }
+        // Get status to separate Holds (on checked out items) and Pages on a
+        $status = $this->getStatus($holdDetails['item_id']);
+        $requestBody = [
+            'requestType' => $item->status->name == 'Available' ? 'Page' : 'Hold',
+            'requestDate' => date('c'),
+            'requesterId' => $holdDetails['patron']['id'],
+            'requester' => [
+                'firstName' => $holdDetails['patron']['firstname'] ?? '',
+                'lastName' => $holdDetails['patron']['lastname'] ?? ''
+            ],
+            'itemId' => $holdDetails['item_id'],
+            'fulfilmentPreference' => 'Hold Shelf',
+            'requestExpirationDate' => date_format($requiredBy, 'Y-m-d'),
+        ];
+        $response = $this->makeRequest(
+            'POST',
+            '/request-storage/requests',
+            json_encode($requestBody)
+        );
+        if ($response->isSuccess()) {
+            return [
+                'success' => true,
+                'status' => $response->getBody()
+            ];
+        } else {
+            throw new ILSException($response->getBody());
+        }
+    }
+
+    // @codingStandardsIgnoreStart
+    /** NOT FINISHED BELOW THIS LINE **/
+
+    /**
+     * Check for request blocks.
+     *
+     * @param array $patron The patron array with username and password
+     *
+     * @return array|boolean    An array of block messages or false if there are no
+     *                          blocks
+     * @author Michael Birkner
+     */
+    public function getRequestBlocks($patron)
+    {
+        return false;
+    }
+
+    /**
+     * This method returns information on recently received issues of a serial.
+     *
+     *     Input: Bibliographic record ID
+     *     Output: Array of associative arrays, each with a single key:
+     *         issue - String describing the issue
+     *
+     * Currently, most drivers do not implement this method, instead always returning
+     * an empty array. It is only necessary to implement this in more detail if you
+     * want to populate the “Most Recent Received Issues” section of the record
+     * holdings tab.
+     */
+    public function getPurchaseHistory($bibID)
+    {
+        return [];
+    }
+
+    /**
+     * This method returns items that are on reserve for the specified course,
+     * instructor and/or department.
+     *
+     *     Input: CourseID, InstructorID, DepartmentID (these values come from the
+     * corresponding getCourses, getInstructors and getDepartments methods; any of
+     * these three filters may be set to a blank string to skip)
+     *     Output: An array of associative arrays representing reserve items. Keys:
+     *         BIB_ID - The record ID of the current reserve item.
+     *         COURSE_ID - The course ID associated with the
+     * current reserve item, if any (required when using Solr-based reserves).
+     *         DEPARTMENT_ID - The department ID associated with the current
+     * reserve item, if any (required when using Solr-based reserves).
+     *         INSTRUCTOR_ID - The instructor ID associated with the current
+     * reserve item, if any (required when using Solr-based reserves).
+     *
+     */
+    public function findReserves($courseID, $instructorID, $departmentID)
+    {
+    }
+
+    /**
+     * This method queries the ILS for a patron's current fines
+     *
+     *     Input: Patron array returned by patronLogin method
+     *     Output: Returns an array of associative arrays, one for each fine
+     * associated with the specified account. Each associative array contains
+     * these keys:
+     *         amount - The total amount of the fine IN PENNIES. Be sure to adjust
+     * decimal points appropriately (i.e. for a $1.00 fine, amount should be 100).
+     *         checkout - A string representing the date when the item was
+     * checked out.
+     *         fine - A string describing the reason for the fine
+     * (i.e. “Overdue”, “Long Overdue”).
+     *         balance - The unpaid portion of the fine IN PENNIES.
+     *         createdate – A string representing the date when the fine was accrued
+     * (optional)
+     *         duedate - A string representing the date when the item was due.
+     *         id - The bibliographic ID of the record involved in the fine.
+     *         source - The search backend from which the record may be retrieved
+     * (optional - defaults to Solr). Introduced in VuFind 2.4.
+     *
+     */
+    public function getMyFines($patron)
+    {
+        return [];
+    }
+
+    /**
+     * Get a list of funds that can be used to limit the “new item” search. Note that
+     * “fund” may be a misnomer – if funds are not an appropriate way to limit your
+     * new item results, you can return a different set of values from this function.
+     * For example, you might just make this a wrapper for getDepartments(). The
+     * important thing is that whatever you return from this function, the IDs can be
+     * used as a limiter to the getNewItems() function, and the names are appropriate
+     * for display on the new item search screen. If you do not want or support such
+     * limits, just return an empty array here and the limit control on the new item
+     * search screen will disappear.
+     *
+     *     Output: An associative array with key = fund ID, value = fund name.
+     *
+     * IMPORTANT: The return value for this method changed in r2184. If you are using
+     * VuFind 1.0RC2 or earlier, this function returns a flat array of options
+     * (no ID-based keys), and empty return values may cause problems. It is
+     * recommended that you update to newer code before implementing the new item
+     * feature in your driver.
+     */
+    public function getFunds()
+    {
+        return [];
+    }
+
+    /**
+     * This method retrieves a patron's historic transactions
+     * (previously checked out items).
+     *
+     * :!: The getConfig method must return a non-false value for this feature to be
+     * enabled. For privacy reasons, the entire feature should be disabled by default
+     * unless explicitly turned on in the driver's .ini file.
+     *
+     * This feature was added in VuFind 5.0.
+     *
+     *     getConfig may return the following keys if the service supports paging on
+     * the ILS side:
+     *         max_results - Maximum number of results that can be requested at once.
+     * Overrides the config.ini Catalog section setting historic_loan_page_size.
+     *         page_size - An array of allowed page sizes
+     * (number of records per page)
+     *         default_page_size - Default number of records per page
+     *     getConfig may return the following keys if the service supports sorting:
+     *         sort - An associative array where each key is a sort key and its
+     * value is a translation key
+     *         default_sort - Default sort key
+     *     Input: Patron array returned by patronLogin method and an array of
+     * optional parameters (keys = 'limit', 'page', 'sort').
+     *     Output: Returns an array of associative arrays containing some or all of
+     * these keys:
+     *         title - item title
+     *         checkoutDate - date checked out
+     *         dueDate - date due
+     *         id - bibliographic ID
+     *         barcode - item barcode
+     *         returnDate - date returned
+     *         publication_year - publication year
+     *         volume - item volume
+     *         institution_name - owning institution
+     *         borrowingLocation - checkout location
+     *         message - message about the transaction
+     *
+     */
+    public function getMyTransactionHistory($patron)
+    {
+        return[];
+    }
+
+    /**
+     * This method queries the ILS for new items
+     *
+     *     Input: getNewItems takes the following parameters:
+     *         page - page number of results to retrieve (counting starts at 1)
+     *         limit - the size of each page of results to retrieve
+     *         daysOld - the maximum age of records to retrieve in days (maximum 30)
+     *         fundID - optional fund ID to use for limiting results (use a value
+     * returned by getFunds, or exclude for no limit); note that “fund” may be a
+     * misnomer – if funds are not an appropriate way to limit your new item results,
+     * you can return a different set of values from getFunds. The important thing is
+     * that this parameter supports an ID returned by getFunds, whatever that may
+     * mean.
+     *     Output: An associative array with two keys: 'count' (the number of items
+     * in the 'results' array) and 'results' (an array of associative arrays, each
+     * with a single key: 'id', a record ID).
+     *
+     * IMPORTANT: The fundID parameter changed behavior in r2184. In VuFind 1.0RC2
+     * and earlier versions, it receives one of the VALUES returned by getFunds();
+     * in more recent code, it receives one of the KEYS from getFunds(). See getFunds
+     * for additional notes.
+     */
+    public function getNewItems($page = 1, $limit, $daysOld = 30, $fundID = null)
+    {
+        return [];
+    }
+
+    // @codingStandardsIgnoreEnd
+}
diff --git a/module/VuFind/src/VuFind/ILS/Driver/FolioFactory.php b/module/VuFind/src/VuFind/ILS/Driver/FolioFactory.php
new file mode 100644
index 0000000000000000000000000000000000000000..a37d4b6a1a5f2adce682bce1ad586d1b33534d6f
--- /dev/null
+++ b/module/VuFind/src/VuFind/ILS/Driver/FolioFactory.php
@@ -0,0 +1,69 @@
+<?php
+/**
+ * Factory for Folio ILS driver.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2018.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  ILS_Drivers
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ */
+namespace VuFind\ILS\Driver;
+
+use Interop\Container\ContainerInterface;
+
+/**
+ * Factory for Folio ILS driver.
+ *
+ * @category VuFind
+ * @package  ILS_Drivers
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ */
+class FolioFactory extends DriverWithDateConverterFactory
+{
+    /**
+     * Create an object
+     *
+     * @param ContainerInterface $container     Service manager
+     * @param string             $requestedName Service being created
+     * @param null|array         $options       Extra options (optional)
+     *
+     * @return object
+     *
+     * @throws ServiceNotFoundException if unable to resolve the service.
+     * @throws ServiceNotCreatedException if an exception is raised when
+     * creating a service.
+     * @throws ContainerException if any other error occurs
+     */
+    public function __invoke(ContainerInterface $container, $requestedName,
+        array $options = null
+    ) {
+        if (!empty($options)) {
+            throw new \Exception('Unexpected options passed to factory.');
+        }
+        $sessionFactory = function ($namespace) use ($container) {
+            $manager = $container->get('Zend\Session\SessionManager');
+            return new \Zend\Session\Container("Folio_$namespace", $manager);
+        };
+        return parent::__invoke($container, $requestedName, [$sessionFactory]);
+    }
+}
diff --git a/module/VuFind/src/VuFind/ILS/Driver/PluginManager.php b/module/VuFind/src/VuFind/ILS/Driver/PluginManager.php
index 020df9446d6be9b4faedbb65917ee780841bed14..0382cdc0b012b1c9c73941fc1b54d2d70e088487 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/PluginManager.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/PluginManager.php
@@ -50,6 +50,7 @@ class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager
         'daia' => 'VuFind\ILS\Driver\DAIA',
         'demo' => 'VuFind\ILS\Driver\Demo',
         'evergreen' => 'VuFind\ILS\Driver\Evergreen',
+        'folio' => 'VuFind\ILS\Driver\Folio',
         'horizon' => 'VuFind\ILS\Driver\Horizon',
         'horizonxmlapi' => 'VuFind\ILS\Driver\HorizonXMLAPI',
         'innovative' => 'VuFind\ILS\Driver\Innovative',
@@ -86,6 +87,7 @@ class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager
         'VuFind\ILS\Driver\Demo' => 'VuFind\ILS\Driver\DemoFactory',
         'VuFind\ILS\Driver\Evergreen' =>
             'Zend\ServiceManager\Factory\InvokableFactory',
+        'VuFind\ILS\Driver\Folio' => 'VuFind\ILS\Driver\FolioFactory',
         'VuFind\ILS\Driver\Horizon' =>
             'VuFind\ILS\Driver\DriverWithDateConverterFactory',
         'VuFind\ILS\Driver\HorizonXMLAPI' =>
diff --git a/module/VuFind/tests/fixtures/folio/responses/check-invalid-token.json b/module/VuFind/tests/fixtures/folio/responses/check-invalid-token.json
new file mode 100644
index 0000000000000000000000000000000000000000..e2f94972372797089da292a7e87ac801804aae63
--- /dev/null
+++ b/module/VuFind/tests/fixtures/folio/responses/check-invalid-token.json
@@ -0,0 +1,5 @@
+[
+  { "status": 400 },
+  { "headers": { "X-Okapi-Token": "x-okapi-token-after-invalid" } },
+  { "body": "{ \"locations\": [] }" }
+]
diff --git a/module/VuFind/tests/fixtures/folio/responses/check-valid-token.json b/module/VuFind/tests/fixtures/folio/responses/check-valid-token.json
new file mode 100644
index 0000000000000000000000000000000000000000..91a26fdc14d70cd7e2d63e36b8cd0e0c616cd2af
--- /dev/null
+++ b/module/VuFind/tests/fixtures/folio/responses/check-valid-token.json
@@ -0,0 +1,4 @@
+[
+  { "status": 200 },
+  { "body": "{ \"loans\": [] }" }
+]
diff --git a/module/VuFind/tests/fixtures/folio/responses/get-tokens.json b/module/VuFind/tests/fixtures/folio/responses/get-tokens.json
new file mode 100644
index 0000000000000000000000000000000000000000..a740982265a3c933179ebdfe8d34d34a70439cfb
--- /dev/null
+++ b/module/VuFind/tests/fixtures/folio/responses/get-tokens.json
@@ -0,0 +1,4 @@
+[
+  { "headers": { "X-Okapi-Token": "x-okapi-token-config-tenant" } },
+  { "body": "{ \"users\": [ { \"id\": \"id\" } ] }" }
+]
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/FolioTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/FolioTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..8242d4da2e9dbd144fcec604d2109d1f7b5763c7
--- /dev/null
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/FolioTest.php
@@ -0,0 +1,192 @@
+<?php
+/**
+ * ILS driver test
+ *
+ * PHP version 7
+ *
+ * Copyright (C) Villanova University 2011.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Tests
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @author   Jochen Lienhard <lienhard@ub.uni-freiburg.de>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org Main Page
+ */
+namespace VuFindTest\ILS\Driver;
+
+use InvalidArgumentException;
+
+use VuFind\ILS\Driver\Folio;
+
+/**
+ * ILS driver test
+ *
+ * @category VuFind
+ * @package  Tests
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org Main Page
+ */
+class FolioTest extends \VuFindTest\Unit\TestCase
+{
+    protected $testConfig = [
+        'API' => [
+            'base_url' => 'localhost',
+            'tenant' => 'config_tenant',
+            'username' => 'config_username',
+            'password' => 'config_password'
+        ]
+    ];
+
+    protected $testResponses = null;
+
+    protected $testRequestLog = [];
+
+    protected $driver = null;
+
+    /**
+     * Replace makeRequest to inject test returns
+     *
+     * @param string $method  GET/POST/PUT/DELETE/etc
+     * @param string $path    API path (with a leading /)
+     * @param array  $params  Parameters object to be sent as data
+     * @param array  $headers Additional headers
+     *
+     * @return \Zend\Http\Response
+     */
+    public function mockMakeRequest($method = "GET", $path = "/", $params = [], $headers = [])
+    {
+        // Run preRequest
+        $httpHeaders = new \Zend\Http\Headers();
+        $httpHeaders->addHeaders($headers);
+        list($httpHeaders, $params) = $this->driver->preRequest($httpHeaders, $params);
+        // Log request
+        $this->testRequestLog[] = [
+            'method' => $method,
+            'path' => $path,
+            'params' => $params,
+            'headers' => $httpHeaders->toArray()
+        ];
+        // Create response
+        $testResponse = array_shift($this->testResponses);
+        $response = new \Zend\Http\Response();
+        $response->setStatusCode($testResponse['status'] ?? 200);
+        $response->setContent($testResponse['body'] ?? '');
+        $response->getHeaders()->addHeaders($testResponse['headers'] ?? []);
+        return $response;
+    }
+
+    /**
+     * Generate a new Folio driver to return responses set in a json fixture
+     *
+     * Overwrites $this->driver
+     * Uses session cache
+     */
+    protected function createConnector($test)
+    {
+        // Setup test responses
+        $file = realpath(
+            __DIR__ .
+            '/../../../../../../tests/fixtures/folio/responses/' . $test . '.json'
+        );
+        if (!is_string($file) || !file_exists($file) || !is_readable($file)) {
+            throw new InvalidArgumentException(
+                sprintf('Unable to load fixture file: %s ', $file)
+            );
+        }
+        $this->testResponses = json_decode(file_get_contents($file), true);
+        // Reset log
+        $this->testRequestLog = [];
+        // Session factory
+        $factory = function ($namespace) {
+            $manager = new \Zend\Session\SessionManager();
+            return new \Zend\Session\Container("Folio_$namespace", $manager);
+        };
+        // Create a stub for the SomeClass class
+        $this->driver = $this->getMockBuilder(\VuFind\ILS\Driver\Folio::class)
+            ->setConstructorArgs([new \VuFind\Date\Converter(), $factory])
+            ->setMethods(['makeRequest'])
+            ->getMock();
+        // Configure the stub
+        $this->driver->setConfig($this->testConfig);
+        $this->driver->expects($this->any())
+            ->method('makeRequest')
+            ->will($this->returnCallback([$this, 'mockMakeRequest']));
+        $this->driver->init();
+    }
+
+    /**
+     * Request a token where one does not exist
+     */
+    public function testTokens()
+    {
+        $this->createConnector('get-tokens'); // saves to $this->driver
+        $profile = $this->driver->getMyProfile(['username' => 'whatever']);
+        // Get token
+        // - Right URL
+        $this->assertEquals('/authn/login', $this->testRequestLog[0]['path']);
+        // - Right tenant
+        $this->assertEquals(
+            $this->testConfig['API']['tenant'],
+            $this->testRequestLog[0]['headers']['X-Okapi-Tenant']
+        );
+        // Profile request
+        // - Passed correct token
+        $this->assertEquals(
+            'x-okapi-token-config-tenant', // from fixtures: get-tokens.json
+            $this->testRequestLog[1]['headers']['X-Okapi-Token']
+        );
+    }
+
+    /**
+     * Check a valid token retrieved from session cache
+     */
+    public function testCheckValidToken()
+    {
+        $this->createConnector('check-valid-token');
+        $profile = $this->driver->getMyTransactions(['username' => 'whatever']);
+        // Check token
+        $this->assertEquals('/users', $this->testRequestLog[0]['path']);
+        // Move to method call
+        $this->assertEquals('/circulation/loans', $this->testRequestLog[1]['path']);
+        // - Passed correct token
+        $this->assertEquals(
+            'x-okapi-token-config-tenant', // from fixtures: get-tokens.json (cached)
+            $this->testRequestLog[1]['headers']['X-Okapi-Token']
+        );
+    }
+
+    /**
+     * Check and renew an invalid token retrieved from session cache
+     */
+    public function testCheckInvalidToken()
+    {
+        $this->createConnector('check-invalid-token');
+        $profile = $this->driver->getPickupLocations(['username' => 'whatever']);
+        // Check token
+        $this->assertEquals('/users', $this->testRequestLog[0]['path']);
+        // Request new token
+        $this->assertEquals('/authn/login', $this->testRequestLog[1]['path']);
+        // Move to method call
+        $this->assertEquals('/locations', $this->testRequestLog[2]['path']);
+        // - Passed correct token
+        $this->assertEquals(
+            'x-okapi-token-after-invalid', // from fixtures: check-invalid-token.json
+            $this->testRequestLog[2]['headers']['X-Okapi-Token']
+        );
+    }
+}
diff --git a/tests/data/folio.mrc b/tests/data/folio.mrc
new file mode 100644
index 0000000000000000000000000000000000000000..912c5bd500b7e40ebee24f831d5de0f49d49a915
--- /dev/null
+++ b/tests/data/folio.mrc
@@ -0,0 +1 @@
+01518cas a22003611a 45  00100370000000500170003700800410005401000360009502200140013103200170014503500160016203700660017804001280024404900170037205000180038921000270040722200400043424500240047424600400049826000450053830000270058331000190061036200570062950000220068650000690070851500310077765000490080865000360085765000320089371000600092578000630098578501080104837b1a546-a826-450b-b57a-9476c4e42b2020091117105557.0840328d19831987nyufx1p   o   0   a0eng d  a   84643014 //r88zsn 84011556 0 a0748-1985  a002051bUSPS  aocm10569413  bHuman Sciences Press, Inc., 72 5th Ave., New York, N.Y. 10011  aKSWcKSWdCLUdAIPdNSTdDLCdNSDdNSTdDLCdHULdNSTdNSDdNLMdNSTdNSDdNSTdNSDdDLCdNSTdNSDdNSTdCLUdNSTdOCLdPVU  aPVUP[SERIAL]00aAC489.R3bJ680 aJ. ration. emot. ther. 0aJournal of rational emotive therapy00a14 cows for America13aJournal of rational-emotive therapy  a[New York] :bThe Institute,c1983-1987.  a5 v. :bill. ;c26 cm.  aTwo no. a year0 aVol. 1, no. 1 (fall 1983)-v. 5, no. 4 (winter 1987).  aTitle from cover.  aVols. for <spring 1985-> published by Human Sciences Press, Inc.  aVol. 1 has only one issue. 0aRational-emotive psychotherapyvPeriodicals. 0aCognitive therapyvPeriodicals. 2aPsychotherapyvperiodicals.2 aInstitute for Rational-Emotive Therapy (New York, N.Y.)00tRational livingx0034-0049w(OCLC)1763461w(DLC)  7200064700tJournal of rational-emotive and cognitive-behavior therapyx0894-9085w(DLC)  88648219w(OCoLC)1630781401234cas a22003011a 45  0010037000000050017000370070014000540080041000680100023001090220014001320300011001460350016001570400083001730500018002562100019002742220020002932450035003132600049003483000028003973620050004255500050004755500132005255800063006576500032007207100060007527100035008127850085008473e38354f-e93a-48f2-b54d-c50265b1504c20091117105643.0hd bfa   b|c|751101d19661983nyufr1p       0   a0eng    a   72000647 //r8520 a0034-0049  aATLVBX  aocm01763461  aDLCcMULdNSDdDLCdRCSdAIPdDLCdNSDdNSTdDLCdAIPdNSTdDLCdNSTdNSDdNST00aAA790.A1bR351 aRation. living 0aRational living00a1963 Birmingham church bombing  a[New York] :bInstitute for Rational Living.  a18 v. :bill. ;c27 cm.0 aVol. 1 (Feb. 1966)-v.18, no. 1 (spring 1983).  aJournal of the Institute for Rational Living.  aIssued by: Institute for Rational Living, Feb. 1966-spring 1982; Institute for Rational-Emotive Therapy, fall 1982-spring 1983.  aContinued in 1983 by: Journal of rational emotive therapy. 0aMental healthvPeriodicals.2 aInstitute for Rational-Emotive Therapy (New York, N.Y.)2 aInstitute for Rational Living.10tJournal of rational emotive therapyx0748-1985w(DLC)  84643014w(OCoLC)1056941301060cas a22003011a 45  001003700000005001700037008004100054010003000095022001400125035001600139037005600155040003300211050002100244210002900265222003800294245001700332260004800349300002800397310001400425362003300439362004000472500002200512650003200534650003500566650004200601785009900643936001600742db08002d-449c-4a21-b154-d083bd20462820091117104735.0820311d19831998nyuqr1p   o   0   a0eng d  a   83-644252 zsn82-2030 0 a0731-7158  aocm08235783  bHaworth Press, 28 E. 22nd St., New York, N.Y. 10010  aNSDcNSDdDLCdAIPdNLMdNST0 aAC455.2.P73bP890 aPsychother. priv. pract. 0aPsychotherapy in private practice00a1990 to 2010  a[New York, N.Y.] :bHaworth Press,c[c1983-  a17 v. :bill. ;c23 cm.  aQuarterly0 aVol. 1, no. 1 (spring 1983)-1 aCeased with: Vol. 17, no. 4 (1998).  aTitle from cover. 2aPsychotherapyvperiodicals. 2aPrivate Practicevperiodicals. 0aPsychotherapyxPracticevPeriodicals.00tJournal of psychotherapy in independent practicex1522-9580w(DLC)sn 98005091w(OCoLC)40524650  aSummer 198401361cas a22003611a 45  00100370000000500170003700700160005400800410007001000170011102200140012803000110014203200170015303500160017003700580018604000630024409000170030721000240032422200400034824500160038826000320040430000170043631000140045336200310046750000220049865000640052065000340058450600660061853000420068471000260072685600960075285601170084893600340096569640328-788e-43fc-9c3c-af39e243f3b720091117105437.0cr  an ---uuuuu840713c19859999nyuqr1p       0   a0eng d  asn 84006638 0 a0748-4518  aJQCRE6  a755730bUSPS  aocm10945712  bPlenum Pub. Corp., 233 Spring St., New York, NY 10013  aNSDcNSDdFUGdNSDdNSTdIULdNSTdHULdNSTdEYMdNSTdHUL  aAV6001b.J721 aJ. quant. criminol. 0aJournal of quantitative criminology00aABA Journal  aNew York :bPlenum,cc1985-  av. ;c23 cm.  aQuarterly0 aVol. 1, no. 1 (Mar. 1985)-  aTitle from cover. 0aCriminal justice, Administration ofxResearchvPeriodicals. 0aCrimexResearchvPeriodicals.  aElectronic access restricted to Villanova University patrons.  aAlso available on the World Wide Web.2 aLINK (Online service)41zOnline version [v. 15 (1999)-present]uhttp://springerlink.metapress.com/link.asp?id=10258641zOff-campus accessuhttp://openurl.villanova.edu:9003/sfx_local?sid=sfx:e_collection&issn=0748-4518&genre=journal  aVol. 1, no. 4 (Dec. 1985) LIC01720cas a22004091a 45  00100370000000500170003700700150005400700140006900800410008301000220012402200140014603000110016003200170017103500160018804000790020405000170028321000200030022200300032024500230035026000430037330000250041636200240044150600660046553000420053155000870057355500420066050001030070265000430080570000360084870000350088470000460091971000490096571000340101485601210104885601170116993600240128625a443d1-541f-4784-b11f-905e43e6e41520091117092424.0cr mn ---|||||hd bda   b|c|750901c19379999ncuqr1p       0   a0eng d  a   40012649 //r86  a0022-3387  aJPRPAU  a281800bUSPS  aocm01588544  aMULcMULdNSDdDLCdNSDdDLCdm.c.dRCSdAIPdNSDdAIPdOCLdDLCdm/cdNST00aAF1001b.J661 aJ. parapsychol. 0aJournal of parapsychology04aaccidental atheist  aDurham, N.C. :bDuke University Press.  av. :bill. ;c23 cm.0 aVol. 1 (Mar. 1937)-  aElectronic access restricted to Villanova University patrons.  aAlso available on the World Wide Web.  aIssued in cooperation with the Duke University Parapsychology Laboratory, 194 -50.  aVols. 1-16, 1937-52, in v. 17, no. 3.  aEditors: Mar. 1937-<Dec. 1938> J. B. Rhine, C. E. Stuart (with W. McDougall, Mar. 1937-Sept. 1938) 0aParapsychologyxResearchvPeriodicals.1 aMcDougall, William,d1871-1938.1 aStuart, Charles Edward,d1907-1 aRhine, J. B.q(Joseph Banks),d1895-1980.2 aDuke University.bParapsychology Laboratory.2 aProQuest Psychology Journals.41zOnline version [v. 59 (1995)-present]uhttp://proquest.umi.com/pqdweb?pmid=000029287&clientId=3260&RQT=318&VName=PQD41zOff-campus accessuhttp://openurl.villanova.edu:9003/sfx_local?sid=sfx:e_collection&issn=0022-3387&genre=journal  aMar. 1937-Dec. 195801536cas a22003371a 45  001003700000005001700037008004100054010003700095022001400132035001600146040003800162041002300200050001500223222004100238245002100279260010900300300002000409310002500429321002200454362005700476500002200533546004100555550017300596580007100769650003800840650003000878710004700908710007500955780008101030785008701111f3cf2855-5dfd-486a-bdf3-465e6a29859920091117105533.0751101d19571970inumr1p      o0   a0eng    aa  53008626 //r853zsc 80001624   a0095-9057  aocm01772601  aDLCcMULdNSDdDLCdm/cdHULdNST0 aengafreageraita0 aAA1b.J975 0aJournal of mathematics and mechanics00aAge of TV heroes  aBloomington, Ind. :bGraduate Institute for Mathematics and Mechanics, Indiana University,cc1957-c1970.  a14 v. ;c26 cm.  aMonthly,b-June 1970  aBimonthly,b1957-0 aVol. 6, no. 1 (Jan. 1957)-v. 19, no. 12 (June 1970).  aTitle from cover.  aEnglish, French, German and Italian.  aVols. for 1957-   published by the Graduate Institute for Mathematics and Mechanics, Indiana University;     -June 1970 by the Dept. of Mathematics, Indiana University.  aContinued in July 1970 by: Indiana University mathematics journal. 0aMechanics, AnalyticvPeriodicals. 0aMathematicsvPeriodicals.2 aIndiana University.bDept. of Mathematics.2 aIndiana University.bGraduate Institute for Mathematics and Mechanics.00tJournal of rational mechanics and analysisw(DLC)sf 85001244w(OCoLC)226307110tIndiana University mathematics journalx0022-2518w(DLC)  75640369w(OCoLC)175301901452cas a22003851a 45  0010037000000050017000370070015000540070014000690080041000830100017001240220014001410300011001550320017001660350016001830370060001990400059002590500014003182100016003322220030003482450032003782600042004103000025004523100022004773210024004993620022005235060066005455000047006115300042006586500029007007000038007297100034007678560122008018560117009239360026010402fb80735-18df-49a9-b4e9-2579c40fd8a720091117102216.0cr mn ---|||||hd bfa   b|c|741112c19369999maubr1p       0   a0eng    a   38003075   a0022-3980  aJOPSAM  a282400bUSPS  aocm01782317  bJournal Press, 2 Commercial St., Provincetown, MA 02657  aDLCcDLCdOCLdDLCdNSDdm.c.dOCLdRCSdAIPdOCLdNSD00aAF1b.J671 aJ. psychol. 4aThe Journal of psychology04aAl Gorehby Rebecca Stefoff  aProvincetown, Mass. :bJournal Press.  av. :bill. ;c25 cm.  aBimonthly,b1965-  aQuarterly,b1935-640 aVol. 1 (1935/36)-  aElectronic access restricted to Villanova University patrons.  aEditor: 1935/36-<Oct. 1937,> C. Murchison.  aAlso available on the World Wide Web. 0aPsychologyvPeriodicals.1 aMurchison, Carl Allanmore,d1887-2 aProQuest Psychology Journals.41zOnline version [v. 128 (1994)-present]uhttp://proquest.umi.com/pqdweb?pmid=000014346&clientId=3260&RQT=318&VName=PQD41zOff-campus accessuhttp://openurl.villanova.edu:9003/sfx_local?sid=sfx:e_collection&issn=0022-3980&genre=journal  aJan. 1975 (surrogate)01267cas a22003251a 45  001003700000005001700037007001500054008004100069010002200110022001400132030001100146035001600157040007300173050001400246210002300260222003800283245003000321260004200351300002500393362002400418506006600442500003000508530004200538650004100580650005200621700001800673710003600691856009700727856011700824d7bcca8e-ec42-464f-8cae-9777a16fb42c20091117102549.0cr an         741112c19569999enkbrzp       0   a0eng    a   57003141 //r830 a0022-3999  aJPCRAT  aocm01782774  aDLCcDLCdNSDdOCLdNSDdDLCdSERdOCLdRCSdDLCdOCLdAIPdOCLdNSD00aAC52b.J61 aJ. psychosom. res. 0aJournal of psychosomatic research00aAl Gorehby Dale Anderson  aLondon ;aNew York :bPergamon Press.  av. :bill. ;c26 cm.0 aVol. 1 (Feb. 1956)-  aElectronic access restricted to Villanova University patrons.  aEditor: 1956-   D. Leigh.  aAlso available on the World Wide Web. 2aPsychosomatic Medicinevperiodicals. 0aMedicine, PsychosomaticxResearchvPeriodicals.1 aLeigh, Denis.2 aScienceDirect (Online service).41zOnline version [v. 44 (1998)-present]uhttp://www.sciencedirect.com/science/journal/0022399941zOff-campus accessuhttp://openurl.villanova.edu:9003/sfx_local?sid=sfx:e_collection&issn=0022-3999&genre=journal02174cas a2200469 a 45000010037000000050017000370060019000540070015000730080041000880100017001290350023001460400050001690220028002190370088002470500013003350490009003481300037003572100026003942220042004202450032004622600070004943100028005643210036005923620031006285000052006595000033007115000095007445060066008395380036009055500120009416500037010616500022010986500029011207100051011497100057012007100025012577760096012827800075013788560122014538560117015759940012016926d6cbb34-edb4-4577-b148-9a33d8d4130420091117160642.0m        d        cr mnu||||||||741112c19659999pauqx pss     0   a0eng d  a  2006212058  a(OCoLC)ocm39109327  aFGAcFGAdOCLdOCLCQdFQMdNSDdEYMdHULdPVU0 a1559-8519y0022-449921  bSociety for the Scientific Study of Sexuality, PO Box 416, Allentown, PA 18105-041614aAQ5b.J6  aPVUM0 aJournal of sex research (Online)1 aJ. sex res.b(Online) 4aThe journal of sex researchb(Online)14aAl Gorehby Tracey Baptiste  aNew York, N.Y. :bSociety for the Scientific Study of Sex,c1965-  a4 issues yearly,b1967-  aThree issues yearly,b1965-19660 aVol. 1, no. 1 (Mar. 1965)-  aTitle from cover (JSTOR, viewed Apr. 18, 2007).  aPlace of publication varies.  aLatest issue consulted: Vol. 43, issue 4 (Nov. 2006) (SSSS website, viewed Apr. 18, 2007).  aElectronic access restricted to Villanova University patrons.  aMode of access: World Wide Web.  aIssued by: Society for the Scientific Study of Sex, 1965-1994; Society for the Scientific Study of Sexuality, 1995- 0aSexologyxResearchvPeriodicals.12aSexvPeriodicals.22aPsychiatryvPeriodicals.2 aSociety for the Scientific Study of Sex (U.S.)2 aSociety for the Scientific Study of Sexuality (U.S.)2 aJSTOR (Organization)08iAlso issued in print:tJournal of sex researchx0022-4499w(DLC)   68130414w(OCoLC)178336500tAdvances in sex research (Online)w(DLC)  2007234124w(OCoLC)12320877540zOnline version [JSTOR: v. 1 (1965)-present ; latest 5 years unavailable]uhttp://www.jstor.org/journals/00224499.html40zOff-campus accessuhttp://openurl.villanova.edu:9003/sfx_local?sid=sfx:e_collection&issn=0022-4499&genre=journal  aC0bPVU01206cas a22003251a 45  00100370000000500170003700700160005400800410007001000170011102200140012803000110014203500160015303700100016904000530017905000180023209000170025021000280026722200430029524500310033826000510036930000170042036200240043750000350046150600660049653000420056265000460060471000200065085600930067085601170076355b3095a-a55b-4411-b532-eb84c47e2c3020091117093002.0cr  bn ---|||||751002c19709999njufr1p       0   a0eng    a   75643076 0 a0047-2662  aJPHPAE  aocm02240975  b07716  aDLCcDLCdNSDdDLCdOCLdRCSdAIPdNSDdOCLdNST0 aAF204.5b.J68  aAF204.5b.J61 aJ. phenomenol. psychol. 0aJournal of phenomenological psychology00aAl Gore and global warming  a[Atlantic Highlands, N.J. :bHumanities Press]  av. ;c23 cm.0 aVol. 1 (fall 1970)-  aAt head of title <1974->: JPP.  aElectronic access restricted to Villanova University patrons.  aAlso available on the World Wide Web. 0aPhenomenological psychologyvPeriodicals.2 aIngenta (Firm).41zOnline version [v. 1 (1970/71)-present]uhttp://www.ingentaconnect.com/content/brill/jpp41zOff-campus accessuhttp://openurl.villanova.edu:9003/sfx_local?sid=sfx:e_collection&issn=0047-2662&genre=journal
\ No newline at end of file