NAV
Shell HTTP JavaScript Ruby Python PHP Java Go

PlanetTerp API v1

Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu.

Welcome to PlanetTerp's API. This API provides access to data relating to courses, professors, and grade data at the University of Maryland — College Park (UMD).

The primary purpose of this API is to provide access to grade and review data. There is already a student-run API that provides access to professor and course data: umd.io.

The course and professor data on this website was obtained using a combination of umd.io and UMD's Schedule of Classes. The grade data is from the UMD Office of Institutional Research, Planning & Assessment (IRPA) and obtained through a request under the state of Maryland's Public Information Act (PIA).

For support, please email admin@planetterp.com.

Base URLs:

Usage

The API does not require any authentication. There are no hard rate limits, but please take a pause between each request.

The API has a Python wrapper on GitHub.

We've written an example program in python using the api for you to follow along with.

Courses

Get a course

Code samples

# You can also use wget
curl -X GET https://api.planetterp.com/v1/course?name=MATH140 \
  -H 'Accept: application/json'

GET https://api.planetterp.com/v1/course?name=MATH140 HTTP/1.1
Host: api.planetterp.com
Accept: application/json


const headers = {
  'Accept':'application/json'
};

fetch('https://api.planetterp.com/v1/course?name=MATH140',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json'
}

result = RestClient.get 'https://api.planetterp.com/v1/course',
  params: {
  'name' => 'string'
}, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json'
}

r = requests.get('https://api.planetterp.com/v1/course', params={
  'name': 'MATH140'
}, headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://api.planetterp.com/v1/course', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://api.planetterp.com/v1/course?name=MATH140");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://api.planetterp.com/v1/course", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /course

Gets the specified courses

Parameters

Name In Type Required Description
name query string true Show the given course.
reviews query boolean false Show reviews for the course (reviews for professors that taught the course and have this course listed as the one being reviewed). Default: false

Example responses

200 Response

{
  "department": "MATH",
  "course_number": 140,
  "title": "Calculus I",
  "description": "Introduction to calculus, including functions, limits, continuity, derivatives and applications of the derivative, sketching of graphs of functions, definite and indefinite integrals, and calculation of area. The course is especially recommended for science, engineering and mathematics majors.",
  "credits": 3,
  "professors": [
    [
      "Jon Snow",
      "Tyrion Lannister"
    ]
  ],
  "average_gpa": 3.17244
}

Responses

Status Meaning Description Schema
200 OK Returns course matching query Course
400 Bad Request bad input parameter None

Get courses

Code samples

# You can also use wget
curl -X GET https://api.planetterp.com/v1/courses \
  -H 'Accept: application/json'

GET https://api.planetterp.com/v1/courses HTTP/1.1
Host: api.planetterp.com
Accept: application/json


const headers = {
  'Accept':'application/json'
};

fetch('https://api.planetterp.com/v1/courses',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json'
}

result = RestClient.get 'https://api.planetterp.com/v1/courses',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json'
}

r = requests.get('https://api.planetterp.com/v1/courses', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://api.planetterp.com/v1/courses', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://api.planetterp.com/v1/courses");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://api.planetterp.com/v1/courses", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /courses

Get all courses, in alphabetical order

Parameters

Name In Type Required Description
department query string false Only get courses in a department. Must be four characters. Default: all departments
reviews query boolean false Show reviews for the course (reviews for professors that taught the course and have this course listed as the one being reviewed). Default: false
limit query integer false Maximum number of records to return. Must be between 1 and 1000. Default: 100
offset query integer false Number of records to skip for pagination. Default: 0

Example responses

200 Response

[
  {
    "department": "MATH",
    "course_number": 140,
    "title": "Calculus I",
    "description": "Introduction to calculus, including functions, limits, continuity, derivatives and applications of the derivative, sketching of graphs of functions, definite and indefinite integrals, and calculation of area. The course is especially recommended for science, engineering and mathematics majors.",
    "credits": 3,
    "professors": [
      [
        "Jon Snow",
        "Tyrion Lannister"
      ]
    ],
    "average_gpa": 3.17244
  }
]

Responses

Status Meaning Description Schema
200 OK Returns courses matching query Inline
400 Bad Request bad input parameter None

Response Schema

Status Code 200

Name Type Required Restrictions Description
anonymous [Course] false none none

Professors

Get a professor

Code samples

# You can also use wget
curl -X GET https://api.planetterp.com/v1/professor?name=Jon%20Snow \
  -H 'Accept: application/json'

GET https://api.planetterp.com/v1/professor?name=Jon%20Snow HTTP/1.1
Host: api.planetterp.com
Accept: application/json


const headers = {
  'Accept':'application/json'
};

fetch('https://api.planetterp.com/v1/professor?name=Jon%20Snow',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json'
}

result = RestClient.get 'https://api.planetterp.com/v1/professor',
  params: {
  'name' => 'string'
}, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json'
}

r = requests.get('https://api.planetterp.com/v1/professor', params={
  'name': 'Jon Snow'
}, headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://api.planetterp.com/v1/professor', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://api.planetterp.com/v1/professor?name=Jon%20Snow");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://api.planetterp.com/v1/professor", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /professor

Get the specified professor.

Parameters

Name In Type Required Description
name query string true Show the given professor.
reviews query boolean false Show reviews for the professor. Default: false

Example responses

200 Response

{
  "name": "Jon Snow",
  "slug": "snow",
  "type": "professor",
  "courses": [
    "MATH140"
  ],
  "average_rating": 4.125
}

Responses

Status Meaning Description Schema
200 OK Returns professor matching query Professor
400 Bad Request bad input parameter None

Get all professors

Code samples

# You can also use wget
curl -X GET https://api.planetterp.com/v1/professors \
  -H 'Accept: application/json'

GET https://api.planetterp.com/v1/professors HTTP/1.1
Host: api.planetterp.com
Accept: application/json


const headers = {
  'Accept':'application/json'
};

fetch('https://api.planetterp.com/v1/professors',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json'
}

result = RestClient.get 'https://api.planetterp.com/v1/professors',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json'
}

r = requests.get('https://api.planetterp.com/v1/professors', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://api.planetterp.com/v1/professors', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://api.planetterp.com/v1/professors");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://api.planetterp.com/v1/professors", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /professors

Get all professors, in alphabetical order

Parameters

Name In Type Required Description
type query string false Show only reviews for professors or teaching assistants. Default: show both. Options: professor, ta
reviews query boolean false Show reviews for the professors. Default: false
limit query integer false Maximum number of records to return. Must be between 1 and 1000. Default: 100
offset query integer false Number of records to skip for pagination. Default: 0

Enumerated Values

Parameter Value
type professor
type ta

Example responses

200 Response

[
  {
    "name": "Jon Snow",
    "slug": "snow",
    "type": "professor",
    "courses": [
      "MATH140"
    ],
    "average_rating": 4.125
  }
]

Responses

Status Meaning Description Schema
200 OK Returns professors matching query Inline
400 Bad Request bad input parameter None

Response Schema

Status Code 200

Name Type Required Restrictions Description
anonymous [Professor] false none none

Grades

Get grades

Code samples

# You can also use wget
curl -X GET https://api.planetterp.com/v1/grades \
  -H 'Accept: application/json'

GET https://api.planetterp.com/v1/grades HTTP/1.1
Host: api.planetterp.com
Accept: application/json


const headers = {
  'Accept':'application/json'
};

fetch('https://api.planetterp.com/v1/grades',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json'
}

result = RestClient.get 'https://api.planetterp.com/v1/grades',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json'
}

r = requests.get('https://api.planetterp.com/v1/grades', headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://api.planetterp.com/v1/grades', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://api.planetterp.com/v1/grades");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://api.planetterp.com/v1/grades", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /grades

Get grades for a course, a professor, or both. If by course, returns all of the grades available by section.

Parameters

Name In Type Required Description
course query string false Show only grades for the given course.
professor query string false Show only grades for the given professor.
semester query string false Show only grades for the given semester. Semester should be provided as the year followed by the semester code. 01 means Spring and 08 means Fall. For example, 202001 means Spring 2020. Default: all semesters
section query string false Show only grades for the given section. Default: all sections

Example responses

200 Response

[
  {
    "course": "MATH140",
    "professor": "Jon Snow",
    "semester": "202001",
    "section": "0101",
    "A+": 1,
    "A": 1,
    "A-": 1,
    "B+": 1,
    "B": 1,
    "B-": 1,
    "C+": 1,
    "C": 1,
    "C-": 1,
    "D+": 1,
    "D": 1,
    "D-": 1,
    "F": 1,
    "W": 1,
    "Other": 1
  }
]

Responses

Status Meaning Description Schema
200 OK Returns grades matching query Inline
400 Bad Request bad input parameter None

Response Schema

Status Code 200

Name Type Required Restrictions Description
anonymous [Grades] false none none

Search

Code samples

# You can also use wget
curl -X GET https://api.planetterp.com/v1/search?query=CMSC13 \
  -H 'Accept: application/json'

GET https://api.planetterp.com/v1/search?query=CMSC13 HTTP/1.1
Host: api.planetterp.com
Accept: application/json


const headers = {
  'Accept':'application/json'
};

fetch('https://api.planetterp.com/v1/search?query=CMSC13',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json'
}

result = RestClient.get 'https://api.planetterp.com/v1/search',
  params: {
  'query' => 'string'
}, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json'
}

r = requests.get('https://api.planetterp.com/v1/search', params={
  'query': 'CMSC13'
}, headers = headers)

print(r.json())

<?php

require 'vendor/autoload.php';

$headers = array(
    'Accept' => 'application/json',
);

$client = new \GuzzleHttp\Client();

// Define array of request body.
$request_body = array();

try {
    $response = $client->request('GET','https://api.planetterp.com/v1/search', array(
        'headers' => $headers,
        'json' => $request_body,
       )
    );
    print_r($response->getBody()->getContents());
 }
 catch (\GuzzleHttp\Exception\BadResponseException $e) {
    // handle exception or api errors.
    print_r($e->getMessage());
 }

 // ...

URL obj = new URL("https://api.planetterp.com/v1/search?query=CMSC13");
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
    new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();
System.out.println(response.toString());

package main

import (
       "bytes"
       "net/http"
)

func main() {

    headers := map[string][]string{
        "Accept": []string{"application/json"},
    }

    data := bytes.NewBuffer([]byte{jsonReq})
    req, err := http.NewRequest("GET", "https://api.planetterp.com/v1/search", data)
    req.Header = headers

    client := &http.Client{}
    resp, err := client.Do(req)
    // ...
}

GET /search

Search both professors and courses with a query string. This will match professors and courses which have the query string as a substring of their name.

Parameters

Name In Type Required Description
query query string true The query to search for
limit query integer false Maximum number of records to return. Must be between 1 and 100. Default: 30
offset query integer false Number of records to skip for pagination. Default: 0

Example responses

200 Response

[
  {
    "name": "CMSC131",
    "slug": "CMSC131",
    "type": "course"
  }
]

Responses

Status Meaning Description Schema
200 OK Returns professors and courses matching the query Inline
400 Bad Request bad input parameter None

Response Schema

Status Code 200

Name Type Required Restrictions Description
anonymous [Search_Result] false none none

Schemas

Course

{
  "department": "MATH",
  "course_number": 140,
  "title": "Calculus I",
  "description": "Introduction to calculus, including functions, limits, continuity, derivatives and applications of the derivative, sketching of graphs of functions, definite and indefinite integrals, and calculation of area. The course is especially recommended for science, engineering and mathematics majors.",
  "credits": 3,
  "professors": [
    [
      "Jon Snow",
      "Tyrion Lannister"
    ]
  ],
  "average_gpa": 3.17244
}

Properties

Name Type Required Restrictions Description
department string true none none
course_number string true none none
title string true none none
description string true none none
credits integer true none none
professors [string] true none none
average_gpa number true none none

Professor

{
  "name": "Jon Snow",
  "slug": "snow",
  "type": "professor",
  "courses": [
    "MATH140"
  ],
  "average_rating": 4.125
}

Properties

Name Type Required Restrictions Description
name string true none none
slug string true none none
type string true none none
courses [string] true none none
average_rating number true none none

Enumerated Values

Property Value
type professor
type ta

Grades

{
  "course": "MATH140",
  "professor": "Jon Snow",
  "semester": "202001",
  "section": "0101",
  "A+": 1,
  "A": 1,
  "A-": 1,
  "B+": 1,
  "B": 1,
  "B-": 1,
  "C+": 1,
  "C": 1,
  "C-": 1,
  "D+": 1,
  "D": 1,
  "D-": 1,
  "F": 1,
  "W": 1,
  "Other": 1
}

Properties

Name Type Required Restrictions Description
course string true none none
professor string true none none
semester string true none none
section string true none none
A+ integer true none none
A integer true none none
A- integer true none none
B+ integer true none none
B integer true none none
B- integer true none none
C+ integer true none none
C integer true none none
C- integer true none none
D+ integer true none none
D integer true none none
D- integer true none none
F integer true none none
W integer true none none
Other integer true none none

Search_Result

{
  "name": "CMSC131",
  "slug": "CMSC131",
  "type": "course"
}

Properties

Name Type Required Restrictions Description
name string true none none
slug string true none none
type string true none none

Enumerated Values

Property Value
type professor
type course