Our application programming interface (API) allows users to write scripts to add content to our site or to search and browse without manually navigating the website. Edit access requires an API token (email us to enable this), though you can search public information without it.
The API is currently under development, and will be subject to change without any promise of backward compatibility as long as the current version described here is version 0. We hope to provide a stable interface soon, at which point we will upgrade to version 1. If you have comments or feature requests or if you want to be informed of the switch to version 1, please visit the API Github issue.
The source code for the API is available here. The example code blocks below are written in Python, but you can use any language able to generate and process HTTP requests.
Encoding
Results are always encoded using json, and requests can be made using either POST or GET (except the save functions, which require POST).
Lookup
You can get public information on a specific series or talk.
def lookup_talk():
from requests import get
url = 'https://researchseminars.org/api/0/lookup/series?series_id="MathOnlineHostingEvents"&series_ctr=1'
r = get(url)
if r.status_code == 200:
J = r.json()
props = J["properties"]
print("%s occurred at %s" % (props["title"], props["start_time"]))
When you look up a series, the result includes a list of talks. Soon, you will be able to specify a date range for those talks.
def lookup_series():
from requests import get
url = 'https://researchseminars.org/api/0/lookup/series?series_id="MITNT"'
r = get(url)
if r.status_code == 200:
J = r.json()
props = J["properties"]
talks = J["talks"]
print("There are %s talks in the %s" % (len(talks), props["name"]))
Searching
You can search for series satisfying certain attributes. If you use the GET method, you can specify a simple query directly in the URL, giving values of attribute according to the schema table below.
def search_series_get():
from requests import get
# Note that America/Los_Angeles is considered different than US/Pacific
url = 'https://researchseminars.org/api/0/search/series?timezone="US/Pacific"'
r = get(url)
if r.status_code == 200:
J = r.json()
results = J["results"]
print("There are %s series in the US/Pacific time zone" % len(results))
If you use the POST method, you can provide more complicated queries by passing in a json query object using the query language described below.
Saving
To save series or talks to the database, you need to provide your program with an API token, which can be found on your account page. If you use git, we highly recommend storing your API token in a separate file that you add to your gitignore so that it isn't accidentally included in a public repository.
def authorization():
# We suggest keeping your api token in a separate file and adding it to your .gitignore
# so that you don't accidentally commit it to your repository
with open("apitoken.txt") as tokenfile:
apitoken = tokenfile.read().strip()
return "roed@mit.edu %s" % apitoken
You can create a new series as follows. Note that organizers cannot be changed through the API for existing series, but you must specify them when creating a new one. The example includes a minimal set of attributes, but you can of course include more from the schema described below.
def create_seminar_series():
from requests import post
url = "https://researchseminars.org/api/0/save/series/"
payload = {"series_id": "test_create",
"name": "creation test",
"is_conference": False,
"topics": ["math_NT"],
"language": "en", # iso639 code
"institutions": ["MIT"],
"timezone": "America/New_York",
"visibility": 1, # 0=private, 1=unlisted, 2=public
"access_control": 0, # 0=open, see schema for more
"slots": ["Mon 15:00-16:00"],
"organizers": [{"name": "Example User",
"email": "user@example.org",
"homepage": "https://example.org/~user/",
"organizer": True, # False for curators, who are not responsible for scientific content
"order": 0,
"display": True}]} # True by default
r = post(url, json=payload, headers={"authorization": authorization()})
J = r.json()
code = J.get("code")
if r.status_code == 200:
if code == "warning":
print("Created with warnings", J["warnings"])
else:
print("Created successfully")
else:
print("Creation failed")
print(J)
Most of the fields are the same for conferences, but you provide start and end dates rather than time slots.
def create_conference():
from requests import post
url = "https://researchseminars.org/api/0/save/series/"
payload = {"series_id": "test_conf",
"name": "Test conference",
"is_conference": True,
"topics": ["math_NT"],
"language": "en", # iso639 code
"institutions": ["MIT"],
"timezone": "America/New_York",
"visibility": 1, # 0=private, 1=unlisted, 2=public
"access_control": 0, # 0=open, see schema for more
"start_date": "June 20, 2020", # we use Python's dateutil.parser
"end_date": "June 23, 2020",
"organizers": [{"name": "Example User",
"email": "user@example.org",
"homepage": "https://example.org/~user/",
"order": 0,
"organizer": True, # False for curators, who are not responsible for scientific content
"display": True}]}
r = post(url, json=payload, headers={"authorization": authorization()})
J = r.json()
code = J.get("code")
if r.status_code == 200:
if code == "warning":
print("Created with warnings", J["warnings"])
else:
print("Created successfully")
else:
print("Creation failed")
print(J)
To edit a series, you need to provide only the fields that you want to change. Note that it is not possible to edit organizers through the API.
def edit_series():
from requests import post
url = "https://researchseminars.org/api/0/save/series/"
payload = {"series_id": "test_conf",
"end_date": "June 25, 2020"}
r = post(url, json=payload, headers={"authorization": authorization()})
J = r.json()
code = J.get("code")
if r.status_code == 200:
if code == "warning":
print("Edited with warnings", J["warnings"])
else:
print("Edited successfully")
else:
print("Editing failed")
print(J)
You can create and edit talks similarly. Each talk has a number, returned to you when you create it, that you include when editing an existing talk.
def create_talk():
from requests import post
from datetime import now, timedelta
url = "https://researchseminars.org/api/0/save/talk/"
# See https://github.com/roed314/seminars/blob/master/Schema.md for more details
payload = {
"series_id": "test_conf",
# Speaker info
"speaker":"Example Speaker",
"speaker_email":"Speaker@Talk.ing", # Only visible to organizers
"speaker_affiliation":"Example Affiliation",
# Talk info
"title":"Talk Title",
"abstract":"Abstract that supports LaTeX",
"start_time":now().strftime('%Y-%m-%dT%H:%M:%S'),
"end_time":(now() + timedelta(hours=1)).strftime('%Y-%m-%dT%H:%M:%S'),
"timezone":"UTC", # Not required per se, copied from seminar series
# Extra info
"online": True,
"access_control":5, # Manual registration
"access_registration":"https://registerehere.doesnotexist",
# !! Leave these out if unavailable
#"slides_link":"http://Unavailable.org",
#"video_link":"http://ToBeUpdated",
#"paper_link":"https://arxiv.org/abs/test"
}
r = post(url, json=payload, headers={"authorization": authorization()})
J = r.json()
code = J.get("code")
if r.status_code == 200:
if code == "warning":
print("Created talk with series_ctr=%s, warned with %s" % (J["series_ctr"], J["warnings"]))
else:
print("Created talk with series_ctr=%s successfully" % (J["series_ctr"]))
else:
print("Creation failed")
print(J)
Approval
After updating series using the API, you must manually approve the changes by logging in and visiting your Manage page. This measure is intended to prevent errors in your scripts from showing up on the live site, and to guard against unauthorized updates if you lose your API token. If this approval is a burden for your intended use, please contact us to discuss its removal.
Schema
More details on the schema will be added here soon. For now, see our schema documentation on Github.
The following columns are available for searching on seminar series and conferences.
| Column | Type |
|---|---|
| access_control | smallint |
| access_hint | text |
| access_registration | text |
| access_time | integer |
| audience | smallint |
| by_api | boolean |
| chat_link | text |
| comments | text |
| deleted | boolean |
| display | boolean |
| edited_at | timestamp with time zone |
| end_date | date |
| frequency | integer |
| homepage | text |
| institutions | text[] |
| is_conference | boolean |
| language | text |
| name | text |
| online | boolean |
| per_day | integer |
| room | text |
| shortname | text |
| start_date | date |
| stream_link | text |
| time_slots | text[] |
| timezone | text |
| topics | text[] |
| visibility | smallint |
| weekdays | smallint[] |
The following columns are available for searching on talks.
| Column | Type |
|---|---|
| abstract | text |
| access_control | smallint |
| access_hint | text |
| access_registration | text |
| access_time | integer |
| audience | smallint |
| by_api | boolean |
| chat_link | text |
| comments | text |
| deleted | boolean |
| deleted_with_seminar | boolean |
| display | boolean |
| edited_at | timestamp with time zone |
| end_time | timestamp with time zone |
| language | text |
| online | boolean |
| paper_link | text |
| room | text |
| seminar_ctr | integer |
| seminar_id | text |
| slides_link | text |
| speaker | text |
| speaker_affiliation | text |
| speaker_email | text |
| speaker_homepage | text |
| start_time | timestamp with time zone |
| stream_link | text |
| timezone | text |
| title | text |
| topics | text[] |
| video_link | text |
Query language
Queries are constructed from dictionaries, where each key gives a constraint for that column. By default, each value is treated as an equality constraint. To get other conditions, the value is also taken to be a dictionary with keys special codes starting with a `$` symbol. For example, use {"topics": {"$contains": "math_NT"}, "abstract": {"$ilike": "%p-adic%"}} to search for a talk having number theory as a topic and having an abstract that contains the string "p-adic". Documentation for the query language will be added here. For now, see the source code for the special keys available.
def search_talks_query_language():
from requests import get
url = '''https://researchseminars.org/api/0/search/talks?topics={"$contains": "math_NT"}&abstract={"$ilike": "%p-adic%"}'''
r = get(url)
if r.status_code == 200:
J = r.json()
results = J["results"]
print("There are %s p-adic number theory talks" % len(results))
Topics
To specify topics, you need to know our identifiers for them. We provide a URL that provides the full topic graph (note that it is not a tree: for instance, mathematical physics is a subtopic of both mathematics and physics).
def topics():
from requests import get
url = "https://researchseminars.org/api/0/topics"
r = get(url)
if r.status_code == 200:
math = r.json()["math"]
print("%s has %s subtopics" % (math["name"], len(math["children"])))
Institutions
Similarly, our identifiers for institutions are listed at the following URL (we don't provide a search interface, because they don't change much).
def institutions():
from requests import get
url = "https://researchseminars.org/api/0/institutions"
r = get(url)
if r.status_code == 200:
MIT = r.json()["MIT"]
print("%s is a %s in %s" % (MIT["name"], MIT["type"], MIT["city"]))
