Developer’s Guide

Introduction

RIC One API provides education application developers with an easy and consistent way to access class roster data, while enabling districts to retain complete control of privacy and security for their students and staff. RIC One is available to all RIC member district in the state of New York. Data is partitioned into 12 regional data providers hosted within the private cloud of the Regional Information Centers.

Authentication

RIC One API supports authenticating using the following methods:

  • Basic
  • OAuth 2.0

RIC One API separates authentication and data access. There is a single authentication endpoint that all apps initially connect to using credentials provided during the onboarding process. Applications login using the username and password provided during the onboarding process to obtain a token and list of regional data providers (endpoints) to which they have been granted access. If your app is used in multiple RICs, you will receive a list containing multiple endpoints. If your app is used only within a single RIC, you will only see a single endpoint in the results of the call to the login service.

Acquire a token

You can retrieve your access token by logging in to http://auth.ricone.org/login. There is a set of test and demo logins available to use for self-testing. By default, tokens expire after 60 minutes and must be refreshed.

Example OAuth Response

In the example below an account with the username of “DemoApp” has logged in and received a JSON payload. This response contains both a token and an array of endpoints. The token received will be used to authenticate at the specified regional provider endpoint. Each endpoint contains information about the provider where the data is located for each of the districts associated to the authenticated application.

{

    "id": "65cda5d0-fa3e-11e4-bad8af5edf5ff602",
   "
user_name": "DemoApp",
   "
endpoint": 
    [
       {
            "name": "NERIC",
           "
href": "https://neric.ricone.org/requests/",
           "
token": "          eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ"
       
},
       
{
           
"name": "SCRIC",
           "
href": "https://neric.ricone.org/requests/",
           "
token": " eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ"    
       
}
   ]
}

All names, values and tokens are for examples purposes only.

Authenticating with your token

Making authenticated calls to the API can be achieved by adding the bearer token to the "Authorization" header. Example:

GET /xStudents HTTP/1.1

Host: https://neric.ricone.org

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

API Responses

RIC One API offers a variety of responses. You can use Response Headers to gain additional insight into your request as well as HTTP status codes to further explain what state your request was when completed. Content-Type fully supports JSON and XML responses, though the default type is XML.

Response Headers

Example Value

Explanation

Navigationpagesize

2

The number of records being requested.

Navigationpage

1

The current page being requested.

Navigationcount

3

Total number of records found.

Navigationlastpage

2

The last page data will be found.

Date

Thu, 14 May 2015 14:54:04 GMT

The date the request started.

Timestamp

2015-05-14T10:54:04Z

The time the request started.

ProviderId

NERICAPI01

The Id of the Provider where the request was placed.

Relativeservicepath

/xSchools

The service path being accessed,

Responseaction

QUERY

The type of request being made.

Content-Type

application/json

The type of data being requested.

HTTP GET Status Response

HTTP Status Code

Definition

Response

200

Ok – The request completed successfully and returned data.

201

Created – Your submission of data has successfully be sent to the server.

204

No Content – The request completed successfully, but no data was found.

401

Forbidden – The request has failed to authenticate, or the service path is invalid.

If you know you are accessing a valid service path then It is possible that your access token has expired and that you may need to generate a new one. Otherwise, check that the service path is valid.

404

Not Found – The page you are requesting does not exist.

Check that the service path you are questing is valid. This error may occur when searching by a reference identifier.

500

Internal Server Error – The API has encountered an unexpected condition.

Wait and try again. If the problem persists please contact your local RIC One API support team.

Developer Resources

Developer Sandbox

The Developer Sandbox is an area that allows application developers a place to familiarize themselves with the data accessible through RIC One API. The sandbox includes an API Explorer http://sandbox.ricone.org and access to a complete sample dataset represented in the SIF xPress data model. This will allow developers to perform GET operations and learn the layout of the RIC One API data models.

API Libraries

We provide client libraries for .NET and Java that you may use as a reference implementation or incorporate directly into your product code.

Data API

Data Models

RIC One API is implemented on a feature rich, open source toolset called the Common Framework. This technology is used widely in Australia and has excellent scaling characteristics. It can easily support multiple API output models. Our featured API is known as xPress Roster. In the future we may support additional standards based on market demand.

xPress Roster API

The RIC One project team developed a standards-based API that has been adopted by the Access For Learning community (A4L, formerly known as the SIF Association) as a part of its North American national standard. You can view the API explorer here: (http://sandbox.ricone.org/SIFxPress/)

The main design goal for the xPress Roster API was to provide an easy to use on-the-wire representation of rosters and necessary related resources. Following is a high level Entity Relationship Diagram that depicts the relationship among the resources.

xPress-Model-Overview.png

Since this model is normalized for interoperability and, for the sake of convenience, most commonly used elements are represented in multiple resources. The underlying physical model within the API provider data store is responsible for maintaining integrity.

Reference Identifiers

In order maintain anonymity and uniqueness, RIC One API assigns each record with a unique reference identifier (refId) or GUID. This is based on Version 4 of the Universally Unique Identifier.

What does a refId look like?

551F9FBE-34FD-4424-B5D4-155E467737C0 

Use of RefIds

Within RIC One API refIds are used for consistency within the system. The refIds are used as a standardized way of filtering data objects to the individual record. For example, if you want to see the full record for an individual student you would request

/xStudents/C15608CB-73E4-4AF2-A89A-0192FEB594CE/

Or the school enrollment of a particular student:

/xStudents/C15608CB-73E4-4AF2-A89A-0192FEB594CE/xSchools


It is recommended that when developing against the Data API, refIds are used as primary key. However natural (SIS) keys are supported for certain resources and service paths.

Student Identifiers (Local)

In addition to refIds, student resources within RIC One API also generally contain the SIS provided primary key, also known as localId. This identifier can be referenced via

  • xStudents.localId

These natural SIS identifiers may be used in place of the refId to query a specific resource. It is generally recommended that refId is used since it is more durable (SIS identifiers can and do change on occasion).

/xStudents/123456789/

Staff Identifiers (Local)

As with Student Identifiers, staff within RIC One API have additional identifiers associated to their record. These include:

  • xStaffs.localId

/xStaffs/123456789/

Scoping Requests for Data
There are multiple strategies you may take to scope requests for data depending on your application's tenancy implementation and data model. Two of the main approaches are to scope by Provider or by District. If you look at the service paths in the table below you can see how you might do this. If you wanted to retrieve all Schools regardless of which district they were a part of you could simply call:

/xSchools

 If you wanted to retrieve a set of Schools based on a district you might do:

/xLeas/{refId}/xSchools

When taking the “By District” approach you will first have to retrieve a list of xLeas and then iterate over them. This approach will require an additional call to the API, but it will increase the overall performance when returning data about any particular object.

See API Library for documentation on how to implement this.

Example:

for(xLea lea : api.request.getXLeas())
{
        for(xSchool school : api.request.getXSchools(lea.refId)
        {
                //now feel free to do anything with your list of schools
        }}

Service Paths

RIC One API offers many ways in which you can retrieve your data. Whether it be through returning all records for a particular object, a single record, or all records by association.

Service Paths by Data Model

Objects on the right are returned using the object on the left and it’s Reference Identifier.

Object

xPress Service Path

Translation

LEAs (i.e. districts or divisions)

xLeas/

All Leas

xLeas/{refId}

Single Lea by refId

xLeas/{refId}/xSchools

Returns Schools associated to a specific Lea by refId

xLeas/{refId}/xCourses

Returns Courses associated to a specific Lea by refId

xLeas/{refId}/xRosters

Returns Rosters associated to a specific Lea by refId

xLeas/{refId}/xStaffs

Returns Staff associated to a specific Lea by refId

xLeas/{refId}/xStudents

Returns Students associated to a specific Lea by refId

xLeas/{refId}/xContacts

Returns Contacts associated to a specific Lea by refId

Schools

xSchools/

All Schools

xSchools/{refId}

Single School by refId

xSchools/{refId}/xLeas

Returns Leas associated to a specific School by refId

xSchools/{refId}/xCalendars

Returns Calendars associated to a specific School by refId

xSchools/{refId}/xRosters

Returns Rosters associated to a specific School by refId

xSchools/{refId}/xStaffs

Returns Staff associated to a specific School by refId

xSchools/{refId}/xStudents

Returns Students associated to a specific School by refId

xSchools/{refId}/xContacts

Returns Contacts associated to a specific School by refId

Calendars

xCalendars/

All Calendars

xCalendars/{refId}

Single Calendar by refId

xCalendars/{refId}/xSchools

Returns Schools associated to a specific Calendar by refId

Courses

xCourses/

All Courses

xCourses/{refId}

Single Course by refId

xCourses/{refId}/xSchools

Returns Schools associated to a specific Course by refId

xCourses/{refId}/xRosters

Returns Rosters associated to a specific Course by refId

xCourses/{refId}/xStaffs

Returns Staff associated to a specific Course by refId

Rosters

xRosters/

All Rosters

xRosters/{refId}

Single Roster by refId

xRosters/{refId}/xSchools

Returns Schools associated to a specific Roster by refId

xRosters/{refId}/xStaffs

Returns Staff associated to a specific Roster by refId

xRosters/{refId}/xStudents

Returns Students associated to a specific Roster by refId

Staff

xStaffs/

All Staff

xStaffs/{refId}

Single Staff by refId

xStaffs/{refId}/xSchools

Returns Schools associated to a specific Staff by refId

xStaffs/{refId}/xRosters

Returns Sections associated to a specific Staff by refId

xStaffs/{refId}/xStudents

Returns Students associated to a specific Staff by refId

Students

xStudents/

All Students

xStudents/{refId}

Single Student by refId

xStudents/{refId}/xLeas

Returns Leas associated to a specific Student by refId

xStudents/{refId}/xSchools

Returns Schools associated to a specific Student by refId

xStudents/{refId}/xRosters

Returns Rosters associated to a specific Student by refId

xStudents/{refId}/xContacts

Returns Contacts associated to a specific Student by refId

Contacts

xContacts

All Contacts

xContacts/{refId}

Single Contact by refId

xContacts/{refId}/xLeas

Returns Leas associated to a specific Contact by refId

xContacts/{refId}/xSchools

Returns Schools associated to a specific Contact by refId

xContacts/{refId}/xStudents

Returns Students associated to a specific Contact by refId

Using Lists

To make the model self documenting multi-valued items are split into two parts: a “primary” and “other” structure. The primary structure can be depended on to provide the main value of interest to most clients. For example, when you see “name” and “otherNames” you would use the “name” field as the primary name for the particular object and, unless your application needs the other names, would ignore those fields. This pattern applies to all items that are potentially multi-valued. This allows us to provide you the best of both worlds: if you only need the primary item from the list just code to look for that primary item; if your application needs additional details, the “other” structure can provide them.

For xStudents the lists include

  • name and otherNames
  • LocalID and otherId’s
  • phoneNumber and otherPhoneNumbers
  • email and otherEmail
  • phoneNumber
  • otherPhoneNumbers
  • enrollment.lea or otherEnrollments.lea

Example of “ids”/”otherIds” and “phoneNumber”/“otherPhoneNumbers” construct in xSchool:

 {

        "@refId": "B8852FA3-C90F-4AAB-AD4F-9940E3CC3E27",

        "leaRefId": "9BA8379D-9A9D-4D59-9202-E976CADF5526",

        "localId": "841552",

        "stateProvinceId": "627776",

        "otherIds": {

          "otherId": {

            "type": "NCES",

            "id": "13835"

          }

        },

        "schoolName": "Arbor Grove Elementary",

        "address": {

          "line1": "102 West Main",

          "city": "Windsor",

          "stateProvince": "NY",

          "postalCode": "13865"

        },

        "phoneNumber": {

          "phoneNumberType": "Main",

          "number": "5554025334",

          "primaryIndicator": "true"

        },

        "otherPhoneNumbers": {

          "phoneNumber": {

            "phoneNumberType": "Other",

            "number": "5555768704",

            "primaryIndicator": "false"

          }

        }

      }

Field Level Access Controls

When using the API your application will only see the subset of the fields your applications is approved for based on the approved security profile. To see what the field set looks like, visit the Security Profiles section of the site. To see a list of the fields your application would receive you need to select the case which best suits your application. If your type of application is not in the profile list then register for the pilot program and let us know what fields your application required.

Paging

Requests to the Data API can return large amounts of data. To increase performance, the use of the API's paging features is recommended.

navigationPage

The navigationPage attribute describes your current location in paging.

navigationPageSize

The navigationPageSize attribute allows you determine the number of results requested per page.

Example Paging Request

The example below shows how you would append these attributes to a service path.

/xSchools?navigationPage=1&navigationPageSize=2

Content Types/Serialization Format

By default the Data API returns results in XML format but supports returning data in JSON. For compatibility with your application, the return type can be specified.

Example XML Call

/xStudents

Example JSON Call

/xStudents.json

"Changes Since"

The “Changes Since” mechanism allows an application to request data that has changed since a given point. The RIC One opaque marker uses an ISO8601 timestamp that indicates a point since the last changes have been requested.

Step 1. Application Requests Changes Since

/xStudents?changesSinceMarker={ISO8601_timestamp}

Step 2: Provider Response

HEADERS

changesSinceMarker: {updated_ISO8601_timestamp}

{changed data}

Step 3: Client Interprets Changes
  • If the refId of a particular object in the response payload does not exist in the consumer’s data store it must be assumed to be NEW (i.e. created).
  • If the refId of a particular object in the response payload does exist in the consumer’s data store it must be assumed to be UPDATED (i.e. changed). It is important to note that the full object is returned not a partial object because there is no way to indicate if the update is partial or full.
  • If a particular object in the response payload contains only the refId the consumer must assume that object to be DELETED.

Note: Applications which choose to use the natural ids as keys in their applications for primary key will not be able to support "Changes Since" fully. Delete events contain only the refId of the object and applications will need to maintain the linking of refIds to natural identifiers (e.g. student.localId, staff.localId)

RIC One Developer’s Guide, 9/28/2017