Getting Started


All Clever API calls must be authenticated using API tokens. Specifically, OAuth 2.0 bearer tokens.

API Tokens

Clever uses token-based authentication because it offers numerous benefits over key-based authentication.

A token represents the authorization that a district has given to access its data. Thus, authenticating with a token only gives you access to the data for a single district.

This approach offers a number of benefits over other systems such as API keys:

  • Security: A compromised token represents a much smaller risk than a compromised API key.
  • Simplicity: With tokens, scoping API calls to be within a single district is trivial.
  • Embedded applications: The content of a token is shared between you and a single district, so it's safe to embed or expose the token to the district that granted it to you.

Acquiring a token

Every time a district authorizes your application, a token is created that stores the details of this authorization. A token is a string of characters:


You can acquire this token in one of three ways:

  1. Manually. After logging into Clever, when you click on a district, the token is present in the detail view:

    A token in the dashboard

  2. Automatically via OAuth 2.0. Every application in Clever can specify a callback URL on its server that Clever will ping upon a new district authorization. This allows partners to capture token information automatically. You can read more about this in the OAuth 2.0 docs.

  3. Query the GET /oauth/tokens endpoint. This endpoint returns a list of every token granted to your application.

Authenticating with a token

Once you have a token, making API calls is a matter of placing this token in the Authorization header of your HTTP requests to the API. For example:

GET /v1.1/students HTTP/1.1

Authorization: Bearer 7f76343d50b9e956138169e8cbb4630bb887b18


Because API tokens grant access to student data, be careful not to expose them! Never email API credentials or post them on public forums. If you are concerned that your API credentials might be exposed, email immediately, and Clever will reset them.

API Responses

There are four types of Clever responses to API requests:

HTTP Response Code Meaning Action
200 Success Process the response
400, 401 Bad Request Check your API token and request body. Do not retry request.
404 Resource not available Check your request url. Resource may have been deleted from Clever. (You can check events for the resource to confirm.)
413 Request entity too large Either a 'page' parameter is over 100 or a 'limit' parameter is over 10,000; reduce accordingly
429 Rate limit exceeded Try again after rate limit period renews
500 - 503 Clever API Failure Wait and retry request.

Exponential Backoff

When a request against the Clever API fails, use a retry with exponential backoff (i.e. wait 1 second after first error, then 2, then 4, etc.). If you are unable to receive a successful response after five retries, you may want to cease the sync and resume at a later time.

See example exponential backoff implementations in PHP and C#.

Rate Limiting

Requests to Clever are rate-limited. Requests are limited to 1200 requests per minute per Bearer Token (student, teacher, or district). These limits are not averages; rather, the allowed count of requests resets every minute.

Rate-limited requests contain these HTTP response headers:

  • X-RateLimit-Reset: Unix timestamp when the rate limit counter will be reset.
  • X-RateLimit-Limit: The total number of requests allowed in a time period.
  • X-RateLimit-Remaining: Number of requests that can be made until the reset time.
  • X-RateLimit-Bucket: Name of the rate-limit bucket for this request


GET /students/123

Response headers:

Status: 200 OK
X-RateLimit-Limit: 200
X-RateLimit-Remaining: 199
X-RateLimit-Reset: 1394506274
X-RateLimit-Bucket: abc123

In case the client hits a rate limit, an empty response with a 429 Too Many Requests status code is returned.


GET /students/123

Response headers:

Status: 429 Too Many Requests
X-RateLimit-Limit: 200
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1394506274
X-RateLimit-Bucket: abc123

Developer Environment

Clever sets up two separate Development and Production apps when you sign up. You can use this feature to ensure that during development you keep sample data separate from real data. For example, the Production app would have access to real district data, and might be shared with the technical lead and the support or implementation team; the Development app would have access to sample data and might be shared with the developers who built the integration.

To edit these apps, see the OAuth Client management page.

Sharing data with your development apps

To share data with your dev app, use a sandbox district account (provided by Clever) and share its data with your application.

  1. Log into Clever using your Sandbox District account
  2. Navigate to{SHORTNAME} Note: Shortname is of the form appname-dev
  3. Click to authorize sharing of data with the dev app

API Clients

Ready to start? Begin by playing around in our API Explorer.

Our API can be accessed via HTTP requests (returns JSON):

import requests
r = requests.get('', headers={'Authorization':'Bearer DEMO_TOKEN'})
schools = r.text

Or via our client libraries (returns a native object):

import clever
schools = clever.School.all()

Check out our libraries, we welcome contributions!

Product Design

Handling Data Gaps

Sometimes school data will contain incomplete information. It is important to determine how your application will handle this.

Clever’s Approach

Clever’s priorities (in order) when handling school SIS data are:

  1. Share only data authorized by the school (e.g. if a school limits sharing to one school, do not share any data outside of that scope).
  2. Share all of the data authorized by the school (e.g. make all students, teachers, and classes from that school available through the API).
  3. Standardize and clean up the data being shared. (i.e. normalize race codes between SISs/districts).
  4. Alert schools and developers to missing or low-quality data (e.g. show data warnings for teachers without an email address).

In light of these priorities, Clever has adopted a permissive data schema with very few required fields (generally, a name, a Clever ID, and a unique identifier). When schools share incomplete records with Clever (e.g. a student with no grade level), rather than reject the record, Clever accepts the record and flags the quality issue as a “Data Warning”.

Best Practices

Often applications written against the Clever API have supplemental data requirements beyond Clever’s required fields. For example, your application might require all students to have birthdays, while Clever does not require this field. Best practices for dealing with this include:

  • Let Clever know your application’s data requirements. With this information, Clever will customize and display Data Warnings for your application and request that districts share all fields that your application requires.

  • Fail gracefully when data requirements are not met. Consider an application that requires all students to have a valid birthday. How should this application handle a student record in Clever without a birthday field?

    • Worst: Processing a student record with a missing birthday raises an unhandled exception. The sync fails and many valid records are not processed.

    • Better: Processing a student record with a missing birthday generates a handled error and a log entry. That student’s account will need to be “resynced” manually at some point, but all valid records are processed.

    • Best (strict): Processing a student record with a missing birthday generates a handled error and a log entry. All other valid records are processed. A future “students.updated” event for that student will result in a successful creation, so long as a birthday is included.

    • Best (permissive): Student records with missing birthdays receive temporary “filler” birthdays, so that accounts can be automatically created. Filler birthdays are replaced by actual birthdays if a “students.updated” event is generated.

  • Build transparency and reporting into your data sync Provide district admin users of your application updates about their Clever sync status. Clever partners often have a “Sync Status” page which displays the current counts of students, teachers, and sections loaded from Clever. This page may show the number of records created, updated, or deleted in the past 24 hours, and any errors that occurred during data sync.

Matching Records

When converting existing customers to a Clever sync, it will likely be necessary to match their existing data with data coming through Clever. Clever recommends identifying fields in your existing data set that are unique and present in the Clever data feed. You can match on these fields, and then store Clever IDs so that future updates will be tied to the newly matched resources.


To match schools in Clever with existing schools in product: Many schools in Clever have NCES IDs (either loaded from the SIS, or pulled by Clever on partner request) which can be helpful for matching schools. However Clever doesn't have 100% coverage, and some schools don't have NCES ids. Many partners have found it relatively easy to match schools by hand (either by the partner or by the school admin), since school matching only has to be completed once.


To match students in Clever with existing students in your product, partners have had success matching on the following fields, in order of most success to least:

  • ID numbers (student_number, state_id, sis_id)
  • birthdays
  • name
  • email address


To match teachers in Clever with existing teachers in your product, partners have had success matching on the following fields, in order of most success to least:

  • email address
  • ID numbers (teacher_number, sis_id)
  • name

Clever does not recommend matching existing sections to sections in Clever, as unique section identifiers rarely exist in existing data sets. If matching sections is essential to your application, matching on school and teacher will make the process simpler.

Clever does not recommend a fully automated match by name because it's very common for more than 1 student in a district (or even more than 1 student in a school) to have the same name.

It’s unlikely that any matching approach will have a 100% success rate. Even if all data is “clean,” there are likely new records or expired records that will not match. As a result, it’s critical for a matching process to allow for a review of failed and questionable matches.

Source of Truth

Deciding whether to allow manual updates or overrides to student data is the most important design decision you will make as you build an integration with Clever. The approach you take will have a major impact on data integrity, school satisfaction, and code complexity.

SIS Lockdown

A straightforward approach to data sync is to treat the district SIS data (as transmitted through Clever) as the single source of truth for roster information. Using this approach, all data that comes from Clever is authoritative and can’t be modified, deleted, or added to. Users may be able to edit supplemental data (e.g. they could set a student’s nickname, as this is not a Clever-provided field).


  • Makes development simple and straightforward. No conflict resolution.
  • Encourages good data practices with schools (e.g. all students must be promptly added to the SIS), pleasing district administrators.
  • Easy to explain to administrators and teachers.


  • Frustrating to teachers if SIS data is outdated or misaligned with use of product.
  • May require development to “lock down” product UI, if current UI supports manual updates.

Two-way Sync

A more complex approach to data sync is to “merge” SIS data (coming through Clever) with manual changes teachers and/or administrators make to roster information. Using this approach, all data can be edited by hand (by users with the appropriate permissions).


  • Very flexible. Gives teachers and/or administrators the ability to resolve changes themselves.


  • Complex development.
  • High risk of sync conflicts or users “fighting” the sync (e.g. user adds student to class, but student is removed from class on next Clever refresh).
  • Can be difficult to explain to teachers/administrators.

Partial Lockdown

This approach is a hybrid of the two earlier sync methods. In this approach, all SIS data is loaded into the product via Clever and “locked down” so that it can’t be modified. However, teachers and/or administrators also have the ability to create “manually managed” resources that will not be synced. In a best practice implementation of this approach, students, teachers, and classes that come from Clever are clearly identified in the UI from manually created resources.


  • More flexible than “lockdown” approach by allowing users to add students and classes that are not in the SIS.
  • Less complex than two way merge (assuming UI indicates automated vs. manual resources).


  • Requires more development effort than “lockdown” approach.
  • Offers users less control than two way merge for some scenarios (e.g. can’t add one student to a class, instead need to manually create a new class with all students).

Manually-Triggered Sync

This approach allows manual updates in the product, and gives users the ability to pick and choose which updates from Clever to apply. Users could choose to “Load all data” from Clever or to “Update this section,” for example.


  • Gives user the ability to ignore data from the SIS (e.g. set up groupings within the product that aren’t over-ridden on subsequent syncs)
  • Gives user the ability to temporarily add information in the product if there’s a lag in the SIS update (e.g. add a student to product, then update from Clever when the SIS is updated)


  • Requires more development effort than other approaches
  • Handling conflicts between users could add complexity


Clever offers an OAuth API, which we recommend as the primary authentication method. See the Single Sign-On guide for details. We recommend username/password login as a secondary authentication method.

Most districts do not store student and teacher usernames and passwords in their SIS, and thus Clever does not recommend relying on the Clever data feed for user credentials.

Districts typically fall into one of three categories regarding their preferences for credentials:

  • Want to use Single Sign-On (SSO)
  • No strong preference, happy to have assigned credentials that they can share with students and teachers (Assign Credentials)
  • Have existing usernames in the SIS and want to pass them through Clever

Assigning Credentials

If you need to assign credentials to students and teachers, Clever recommends the following strategies:


Username: We recommend giving schools a few choices - possibly differentiated by grade level (ex. 1st graders need simpler options than 10th graders). Some popular options include: FLast, FirstL, student_number.

Password (DEPRECATED): To improve the security of sensitive credentials, Clever will remove student and teacher passwords from the API on January 31st, 2016 (usernames will still be available). See for more details on the deprecation.

If you need passwords, Clever recommends generating your own passwords using sensible defaults (e.g. a default word such as "banana" or the student's ID) and requiring the student or teacher to change the password afterwards.


We strongly recommend using a teacher’s email address as his/her username. Teacher emails are typically stored in the SIS, and are available through the Clever API.

We recommend inviting teachers to their accounts via email and letting them set own password on first login.

We recommend allowing teachers and administrators to reset teacher passwords.

Usernames from Clever

If a district is sending data to Clever via SFTP, you can request that they include student and teacher usernames in their files. If this information is not stored in the SIS, they may have trouble automating their exports. You might choose to let them set usernames initially via the Clever feed, but then ignore any updates to usernames. This will allow you to preserve credentials even if a district omits them from the feed.

If a district is sending data to Clever via an Automatic SIS connection, the district can request that Clever create custom mappings for their credential fields. The district must have student and teacher credentials stored in exportable fields in their SIS. Clever is unable to combine fields to create a username or password, or take partial data from a field (ex. if the field contains, username would be Clever cannot pull “jsmith”).

Student usernames coming from Clever are found in students.credentials.district_username.

Teacher usernames coming from Clever are found in teachers.credentials.district_username.

Uniqueness Requirements

Clever does not guarantee uniqueness of the district_username field provided through the API. The API passes through the values that the district provides. Username conflicts should be identified in your application, and the district must resolve conflicts by changing the information that they’re sending through Clever.

Clever recommends that you do not require unique usernames across your entire product. Because districts often use usernames such as firstinitiallastname, it is common to find conflicting usernames in different districts. Requiring uniqueness across the product will lead to frustration for districts that have existing username conventions that collide with those of other districts. Districts should be able to comply with providing usernames that are unique within a school or within a district.

Password Best Practices

When defining password requirements, keep the needs of younger students in mind. Kindergarteners and first and second graders may struggle to remember (and type) seemingly simple passwords such as “apple” or “banana.” Schools’ biggest concerns are usually: Avoiding wasting class time to deal with a student’s forgotten password (make resets easy) Students gaining access to peer accounts by guessing a password (be sure to address ability to reset password and restore account to original owner) Passwords that are too difficult for students to remember and use with ease



For an overview of the resources and fields available from the Clever API, see the data schema summary (or download as Excel).

Clever IDs

Clever assigns all top-level resources a stable Clever ID, or GUID. Clever IDs are globally unique within each resource type.

Clever strongly recommends you store the Clever ID for each resource, and use the Clever ID as the link between your database and the Clever API data. Events in Clever reference Clever IDs, as do links between resources.

Will a Clever ID ever change?

Typically no. One exception is if the sis_id were to change, addressed below.

Maintaining constant student and teacher records with the Clever ID

Clever IDs remain constant even if a student or teacher moves between schools in the same district. Further, if a student or teacher is removed from the SIS and the Clever API, then re-added within 150 days, they will be recreated with the same Clever ID. When notified in advance by the district, Clever IDs can maintain stability across changes to a new SIS, even if district identifiers change.

Will a student’s Clever ID change if he or she moves to a new district?

Yes – Clever does not currently maintain ID stability across districts.

Student Identifiers

In addition to their Clever ID, students in Clever often have several other IDs. These include sis_id and student_number.

What's the point of each field?

sis_id is a database identifier in the student information system. Ideally, the sis_id is the primary key for the record in the SIS database - a stable identifier that can't be changed by a SIS user.

student_number (or teacher_number) field is a student-visible identifier. While most would assume this to be stable, it changes more often than most people expect, which is why Clever recommends always keying on Clever ID.

Where is sis_id for SFTP systems?

For SFTP systems, the value of the student_id and teacher_id columns are mapped to sis_id in the API.

What happens if sis_id changes?

Clever assumes sis_id is constant. If sis_id changes, Clever treats this as a delete/create event. The sis_id field is required.

What happens if a student or teacher number changes?

Clever allows student_number/teacher_number to change. If these fields change, Clever treats this as an updated event. Clever does not require this field to operate.

In Practice

Fields are generally used as intended, but there are some exceptions.

In some systems, there is no distinction between a "primary key" and a "user-editable ID". In that case, we use the same value for sis_id and student_number.

In some systems, the student_number is sufficiently stable to be used as the sis_id and the student_number.

In some systems (primarily SFTP), the user may have not set a value for student_number/teacher_number. (this is most likely unintended and fixable by the school).

Handling identifiers?

When in need of a stable identifier or a link between records, use Clever ID (this will allow for easy Student -> Section or Event -> resource links). When attempting to match on ID or set a username, student_number/teacher_number is the best option. When student_number/teacher_number is not available, or does not produce a match, sis_id can be used as a fallback.

Resource Associations

Clever makes several assumptions on the associations between students and schools, teachers and schools, and sections and schools:

Students, teachers, and sections are always associated with one school in Clever.

Each resource (student, teacher, section) has a required school property that is the Clever ID of the associated school.

Students and Teachers can be associated with any section in their district.

A student in School A can be enrolled in a class in School B that is taught by a teacher in School C.

In some SISs, a teacher or student (with one ID) can be affiliated with > 1 school.

Clever handles these situations by associating the teacher or student with their "primary school" (if that information is available). If that information is not available, Clever associates the teacher or student with only one of their schools. If a district sends Clever a SFTP upload with two rows for a teacher or student (e.g. attempting to associate them with > 1 school), Clever discards one of the rows.

In some situations, a district may create duplicate accounts (with different IDs) for students and teachers who are affiliated with > 1 school.

This is most often seen with teacher accounts in districts using older versions of PowerSchool (< 7.8). In this scenario, because there are two accounts in the SIS with two separate IDs, Clever creates two separate student or teacher resources.

Co-teachers in sections

As of January 2015, sections can be associated with up to four teachers. Support for co-teachers is currently limited, with support rolled out for some of the SISs Clever supports and new SISs added regularly.

The primary instructor is indicated in the teacher field, while the full collection of Clever IDs for the section's "co-teachers" can be found in the teachers array associated with section objects.

The primary teacher is also included in the teachers array. Sections with no teacher assigned will specify an empty teachers array.

Use the DEMO_TOKEN in the API explorer or while prototyping to work with co-teachers if it is not yet supported for your districts. Look for sections by these IDs: 54b8195ed947e6ed602dd562 and 54b8195ed947e6ed602dd563.


Queries on the Clever API can return large numbers of results. To improve performance and make the data more consumable, the Clever API supports paginating large responses.

To iterate through results, you should follow the rel:next link contained with every set of results. For example:

"links": [
      "rel": "next",
      "uri": "/v1.1/students?starting_after=530e5961049e75a9262cffe4"

The link uses the starting_after parameter to jump to the next page of results. This form of pagination is called range-based pagination. Elements are returned sorted with ascending IDs (based on create time). Since range-based pagination is sensitive to the ordering of IDs, you cannot use range-based pagination and the sort parameter simultaneously.

NOTE: Clever is deprecating support for pagination using the page parameter. Requests using the page parameter still work, but request for page numbers of 100 or above will result in a 413 error code.


Rather than serving every result at once, by default the Clever API limits the number of entries in responses to 100 per page. You can change the number of results returned by setting the limit parameter. For instance:

GET /v1.1/districts?limit=30  # returns at most 30 districts


Due to the presence of limits, a request may not return every result. Therefore, each request contains a set of “hypermedia links,” URLs that let you access related data to the current request. If there are more results to consume, the response’s links object will have a rel link called next, that lets you query the next page of results. Similarly, there may be a prev link for the previous page of results.

It is highly encouraged to use hypermedia links when possible. Doing so will make your code more robust to changes in the API, and should also simplify your logic.

Example links object for request GET /v1.1/districts?starting_after=53ced71e65a64d5918157c04:

"links": [
        "rel": "self",
        "uri": "/v1.1/districts?starting_after=53ced71e65a64d5918157c04"
        "rel": "next",
        "uri": "/v1.1/districts?starting_after=56fad73b82c6fd818c6b48cc"
        "rel": "prev",
        "uri": "/v1.1/districts?ending_before=53ced71e65a64d5918157c04"

NOTE: starting_after queries may have prev links even when there are no previous results. Following such links will return an empty array of data. Similarly, ending_before queries may have next links even when there are no more results, and following those links will return an empty array.


paging - (Deprecated)

Metadata related to numeric-based pagination is stored in the paging object in in responses for numerically-paged or unpaginated responses. It contains three fields:

* count: The total number of entries, including those in current and previous pages.
* total: The total number of pages, including current and previous pages.
* current: The index of the page being viewed, beginning at 1.

These metadata fields are deprecated and will be removed in the future.

Working with Events

Clever offers an events endpoint that describes changes to a district's data. If you are using events, you should be able to perform an initial sync or resync directly from the main data endpoints (students, teachers, etc.) The events endpoint is offered only as a convenience for keeping up with changes. Processing data from the events endpoints should be idempotent, meaning that processing the same event multiple times should result in no change of state.

Requests made directly to the /events endpoint are scoped to a single district, based on the use of a district token for authorization.

This is the recommended flow for working with events:

  • Make a request to obtain the single most recent event, and save its ID:


  • Perform an initial sync using the non-event endpoints: districts, schools, students, teachers, sections

  • On subsequent syncs, request the events that are new (ie, starting after the previously-processed event id):


Note that starting_after requires a valid event_id, so if there is no previously processed event, then do not pass in the parameter.

Instant Login


Clever's single sign-on flow, Instant Login, allows any student or teacher to easily sign into your product without having to remember an additional username or password. The flow is built using the OAuth2 standard.

Three Steps to Implementation

Each step is described in its own section of the docs.

  1. Add an endpoint/route on your application server to handle OAuth login requests (must be HTTPS, we recommend Your endpoint will:

    • POST with code to get a token
    • GET /me with token to get the user's unique Clever identifier
    • Log the user in to your application
    • Optionally, look up further profile information about the user if granted the appropriate scopes

    Take a look at our example implementations in PHP and Python.

  2. Configure your OAuth Applications on your OAuth Application management page. You should have a production app and a dev app, which you will need to configure and test individually.

  3. Test your endpoint using your sandbox district account.

OAuth2 Flow

This section describes a student logging into the ReadingFun application using Clever's OAuth flow.

User Initiates Login to ReadingFun

There are two ways that the sign-on flow can be initiated:

  • From a student's Clever account (Clever initiates)
  • From a district-specific login page on an application's website (ReadingFun initiates)

Clever Initiates

Within the Clever dashboard, a student clicks on the ReadingFun icon.

Application Initiates

To initiate the login flow from their website, ReadingFun includes a 'Log in with Clever' button that links to a specific URL:


If the user is not already logged into Clever, they will be prompted to choose their district before signing in; after they are logged in to Clever, they are immediately redirected back to the redirect URI on the application website.

'Log in with Clever' buttons no longer require specifying a district ID. If you're providing district-specific login pages, you may still provide an explicit district ID to skip Clever's district picker experience.

To use the district picker while in development, simply copy and paste the district ID of your sandbox district into the district picker's search field.

The parameters of the URL are as follows:

Parameter Example Description
client_id 123456 Your app's client_id
redirect_uri One of the redirect URIs specified in the OAuth Application settings. It should be the URI on your app's site that will handle the OAuth flow.
response_type code Must be code
state 10101010 (optional) A nonce that is passed back to the redirect url
district_id 4fd43cc56d11340000000005 (optional) A district's Clever ID. If unprovided, Clever will present users with a district selection interface.

To initiate the 'Log in with Clever' flow, use one of these button images:

User Directed to ReadingFun URI

The student's click directs her browser to the ReadingFun redirect URI, specified by the application's OAuth Client management page.


ReadingFun Redeems Code for Token

ReadingFun grabs the code and exchanges it for a token by making a request to /oauth/tokens.

Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=

  "code": "abc123",
  "grant_type": "authorization_code",
  "redirect_uri": ""

Note that the authorization string is computed as the base64 encoding of "<client id>:<client secret>".

The body of the request must have the following parameters:

Parameter Example Description
code abc123 The code received from the redirect
grant_type authorization_code Must be authorization_code
redirect_uri One of the redirect URIs specified in the OAuth Application settings. Must match the redirect URI that was used to initiate the flow.

The response is JSON and contains an access token.


This token grants access to various pieces of info about the user based on ReadingFun's requested scopes: read:user_id and read:students.

ReadingFun Looks Up User

With the access token, ReadingFun's server can make a request to /me to look up information about the user trying to sign in. ReadingFun is allowed to access /me because they have been granted the read:user_id scope.

Authorization: Bearer def456

The response is JSON, identifying the user by ID, user type, and district:

  "data": {
    "district": "4fd43cc56d11340000000005",
    "id": "4fee004cca2e43cf2700028b",
    "type": "student"
 "links": [
      "uri": "/me",
      "rel": "self"
      "uri": "/v1.1/students/4fee004cca2e43cf2700028b",
      "rel": "canonical"
      "uri": "/v1.1/districts/4fd43cc56d11340000000005",
      "rel": "district"

The user type may be "student", "teacher", or "district".

ReadingFun Matches and Logs in User

Using the type and id fields in the response from the /me endpoint, ReadingFun identifies the user, establishes a session, and directs her to the appropriate content.

ReadingFun Looks Up Additional User Info

Since ReadingFun requested the read:students scope in addition to read:user_id, they are allowed to use the same student token to look up additional profile information about the student using the /students/{id} endpoint with the ID returned by /me. (Note that if ReadingFun did not have the read:students scope, but instead had the read:sis scope, they would instead use their district token to look up the student's full profile info, including roster info.)

Authorization: Bearer def456

The response is JSON and contains profile info about the student:

  "data": {
    "id": "4fee004cca2e43cf2700028b",
    "district": "4fd43cc56d11340000000005",
    "school": "530e595026403103360ff9fe",
    "credentials": { "district_username": "maryj" },
    "dob": "2/11/1980",
    "email": "",
    "grade": "Kindergarten",
    "name": {
      "first": "Mary",
      "middle": "J",
      "last": "Berry"
    "sis_id": "100095233",
    "state_id": "231786324",
    "student_number": "100095233"

Handling Logout

Upon logout, you should destroy the user's session and either close the browser window or redirect to a splash page on your site. You do not need to redirect the user's browser to Clever.

Clever does not currently support a programmatic way of logging out a user. The Clever session will expire when the browser closes or after two hours, whichever happens first.


The Clever OAuth flow grants tokens with different scopes. The scopes are configured per application and are managed by Clever. When you register your application with Clever, you will specify the set of scopes your application requires. When a student or teacher uses Clever to log in to your application, your application will be granted a token with these scopes.

Name Description
read:user_id Grants access to the /me endpoint, which returns a user's anonymous Clever identifier as well as the user type ('student', 'teacher' or 'district')
read:students Grants access to the /students/{id} endpoint, which returns a student's profile info.
read:teachers Grants access to the /teachers/{id} endpoint, which returns a teacher's profile info.
read:sis Grants full access to the Clever Data API, which includes full student and teacher info as well as roster data.
read:user deprecated Grants access to student and teacher profile info.

You can see your app's scopes on the OAuth Application management page.

Matching Users

You will either be matching the user to an existing account or creating one for them. Whenever possible, you should match users based on their Clever ID, stored in the id field. It may also be possible to match on the sis_id, email, or username fields, depending on the type of user and their school district. In this situation, please discuss matching with Clever Developer Support.


Your dev and prod apps have different client_ids, client_secrets, and redirect_uris. You will need to configure and test them individually. Production apps are required to use HTTPS, but dev apps may use HTTP and redirect to localhost.

To test the OAuth flow, you can log into Clever as one of the fake users from your sandbox district. (Developers log in with a username and password because sandbox districts don't have corresponding Google Apps or Active Directory accounts that can be used for testing.)

  1. Make sure your sandbox school district includes usernames and passwords. These come from the dataset that was uploaded, and are available from the API in the student or teacher object:
"credentials" : {
      "district_username" : <username>,
      "district_password" : <password>
  1. Make a request to the URL that will initiate the OAuth flow for your test district. The format is described above in the section on application-initiated login.

  2. You are presented with the Clever login screen for the district; click the login button, and then fill in a username and password for a test student/teacher

  3. You should be redirected to the OAuth endpoint of your application.

Alternately, you can configure your sandbox district so that you initiate login from the Clever dashboard of a test student. To do this in your sandbox district, go to Instant Login Settings and set up Instant Login using 'Username/Password' as the authentication method; you will also need to select your dev app to show up for teachers and students.

District Tokens via OAuth

You may programmatically receive OAuth tokens from districts who authorize your app.

When you access the /me endpoint with a token, districts are identified by a user type of "district". The token you receive from that district is also provided on your admin dashboard; you can save it and use it to access district data from the Clever API.

Clever-initiated Signups

Most districts authorize an app on Clever's website; when this occurs, Clever will automatically send an OAuth request to your redirect URI, as described above.

Application-initiated Signups

You may also initiate the OAuth flow for a district from a link on your website. Clever will send a request to the first redirect URI specified in your OAuth Application settings. The URL should be of this form:{shortname}

Testing Application-initiated Signups

To test acquiring the district token via OAuth, send a request to the following URL. Make sure you are logged into Clever as a sandbox district. You may specify a redirect URI of your choice, as long as it is also specified in your OAuth settings. The redirect URI also needs to be publicly resolvable, because Clever sends a request to it from our servers.{shortname}?
Parameter Example Description
redirect_uri The test URI on your site that handles the OAuth flow
state 10101010 An optional nonce that is passed back to the redirect URI

Instant Login on Mobile

Native mobile applications, whether on iOS or Android, are increasingly popular in schools. Instant Login can be used on native mobile applications as well as web applications. While we don't currently offer a native SDK for integrating Instant Login, our web-based flow works great on mobile devices.

For more information, please read our Clever Instant Login for Mobile guide on

Additional Resources

Recent Updates

February 2015

  • February 18: "Log in with Clever" buttons no longer require a district_id. When omitted, Clever will provide students and teachers with a district picker interface.

January 2015

October 2014

  • October 9: Updated API to always return properly escaped rel links.
  • October 6: Updated documentation of /me endpoint. /me now contains an array of "links".

September 2014

  • September 17: Updated documentation to reflect that the scopes paramater is not required when initiating OAuth requests.
  • September 5: Added GET /oauth/tokens endpoint, which lists every district token granted to a given application. Added documentation for this endpoint.

August 2014

  • August 28: Clarified that API key rate-limiting is live, and API keys authentication will be fully removed on March 1, 2015.
  • August 22: Updated Instant Login documentation to provide more detail on scopes, among other minor clarifications.
  • August 22: districts.created events are no longer returned when pulling events using token auth.
  • August 17: Provided guidance on iterating through events.
  • August 17: Removed range_paging metadata to improve performance.
  • August 15: Removed "lowest" and "highest" parameters from range_paging metadata. Made entries_remaining, pages_remaining counts in range_paging exclusive of current page. Fixed bug that caused "next" rel links to appear on the final page of a query. Add documentation for range_paging and paging objects to guide.
  • August 13: Restricted numeric-paging to the first 100 pages of results.
  • August 13: Replaced references to to /oauth/tokens.
  • August 6: Added a note to API Explorer clarifying that demo data set will not always match actual school data.

July 2014

  • July 30: Fixed a bug introduced by range-based pagination rollout that prevented queries on Events that used the "created_since" and "page" parameters together.
  • July 29: Each OAuth app now has a single set of credentials, rather than two. Each developer has a dev app and a prod app.
  • July 25: Released range-based pagination, an improved way to iterate through large data sets. See "starting_after" and "ending_before" parameters in Interactive Docs.
  • July 24: Fixed a bug that could cause token-authenticated requests to the /events endpoint to return events scoped to an API_KEY, rather than a token.
  • July 18: Added documentation for Instant Login on handling logout
  • July 17: Updated the URL and parameters for obtaining district tokens via OAuth
  • July 15: Fixed bug in /me endpoint. "type" property now exists inside of "data" object, matching spec. We will maintain the "type" property outside of the "data" object until 12/31/2014, to preserve backwards compatibility.

June 2014

  • Added support for Instant Login initiated from a partner's website


March 2015

  • March 1: Feature retirement: API keys will no longer be accepted when authenticating API requests. Use bearer tokens instead.

January 2016

  • January 31: Feature retirement: district passwords will no longer be returned in API responses. We recommend using Instant Login to authenticate users instead.
  • January 31: Feature retirement: simple pagination with 'page' parameters will no longer be supported. Use cursored pagination with relative links, starting_after, and ending_before parameters instead.
  • January 31: and retired; use and instead.