diff --git a/src/_repobee/ext/github.py b/src/_repobee/ext/github.py
index 3bb248f..657a413 100644
--- a/src/_repobee/ext/github.py
+++ b/src/_repobee/ext/github.py
@@ -129,6 +129,17 @@ class GitHubAPI(plug.API):
         """
         if not user:
             raise TypeError("argument 'user' must not be empty")
+        if not (
+            base_url == "https://api.github.com"
+            or base_url.endswith("/api/v3")
+        ):
+            raise plug.PlugError(
+                "invalid base url, should either be https://api.github.com or "
+                "end with '/api/v3'. See the docs: "
+                "https://repobee.readthedocs.io/en/stable/"
+                "getting_started.html#configure-repobee-for-the-target"
+                "-organization-show-config-and-verify-settings"
+            )
         self._github = github.Github(login_or_token=token, base_url=base_url)
         self._org_name = org_name
         self._base_url = base_url

diff --git a/tests/unit_tests/plugin_tests/test_github.py b/tests/unit_tests/plugin_tests/test_github.py
index 959aafc..84ead19 100644
--- a/tests/unit_tests/plugin_tests/test_github.py
+++ b/tests/unit_tests/plugin_tests/test_github.py
@@ -317,6 +317,32 @@ def api(happy_github, organization, no_teams):
     return _repobee.ext.github.GitHubAPI(BASE_URL, TOKEN, ORG_NAME, USER)
 
 
+class TestInit:
+    def test_raises_on_empty_user_arg(self):
+        with pytest.raises(TypeError) as exc_info:
+            _repobee.ext.github.GitHubAPI(BASE_URL, TOKEN, ORG_NAME, "")
+
+        assert "argument 'user' must not be empty" in str(exc_info.value)
+
+    @pytest.mark.parametrize("url", ["https://github.com", constants.HOST_URL])
+    def test_raises_when_url_is_bad(self, url):
+        with pytest.raises(plug.PlugError) as exc_info:
+            _repobee.ext.github.GitHubAPI(url, TOKEN, ORG_NAME, USER)
+
+        assert (
+            "invalid base url, should either be https://api.github.com or "
+            "end with '/api/v3'" in str(exc_info.value)
+        )
+
+    @pytest.mark.parametrize(
+        "url", ["https://api.github.com", constants.BASE_URL]
+    )
+    def test_accepts_valid_urls(self, url):
+        api = _repobee.ext.github.GitHubAPI(url, TOKEN, ORG_NAME, USER)
+
+        assert isinstance(api, plug.API)
+
+
 class TestEnsureTeamsAndMembers:
     @staticmethod
     def assert_teams_equal(actual_teams, expected_teams):

Add a check for GitHub base url
Check that the url is either `https://api.github.com`, or that it ends with `/api/v3`. There have been way too many user errors on incorrect urls, and the error messages can be cryptic.
tests/unit_tests/plugin_tests/test_github.py::TestInit::test_raises_when_url_is_bad[https://github.com] tests/unit_tests/plugin_tests/test_github.py::TestInit::test_raises_when_url_is_bad[https://some_enterprise_host]
tests/unit_tests/plugin_tests/test_github.py::TestInit::test_raises_on_empty_user_arg tests/unit_tests/plugin_tests/test_github.py::TestInit::test_accepts_valid_urls[https://api.github.com] tests/unit_tests/plugin_tests/test_github.py::TestInit::test_accepts_valid_urls[https://some_enterprise_host/api/v3] tests/unit_tests/plugin_tests/test_github.py::TestEnsureTeamsAndMembers::test_no_previous_teams tests/unit_tests/plugin_tests/test_github.py::TestEnsureTeamsAndMembers::test_all_teams_exist_but_without_members tests/unit_tests/plugin_tests/test_github.py::TestEnsureTeamsAndMembers::test_raises_on_non_422_exception[unexpected_exc0] tests/unit_tests/plugin_tests/test_github.py::TestEnsureTeamsAndMembers::test_raises_on_non_422_exception[unexpected_exc1] tests/unit_tests/plugin_tests/test_github.py::TestEnsureTeamsAndMembers::test_raises_on_non_422_exception[unexpected_exc2] tests/unit_tests/plugin_tests/test_github.py::TestEnsureTeamsAndMembers::test_running_twice_has_no_ill_effects tests/unit_tests/plugin_tests/test_github.py::TestCreateRepos::test_creates_correct_repos tests/unit_tests/plugin_tests/test_github.py::TestCreateRepos::test_skips_existing_repos tests/unit_tests/plugin_tests/test_github.py::TestCreateRepos::test_raises_on_unexpected_error[unexpected_exception0] tests/unit_tests/plugin_tests/test_github.py::TestCreateRepos::test_raises_on_unexpected_error[unexpected_exception1] tests/unit_tests/plugin_tests/test_github.py::TestCreateRepos::test_raises_on_unexpected_error[unexpected_exception2] tests/unit_tests/plugin_tests/test_github.py::TestCreateRepos::test_returns_all_urls tests/unit_tests/plugin_tests/test_github.py::TestCreateRepos::test_create_repos_without_team_id tests/unit_tests/plugin_tests/test_github.py::TestGetRepoUrls::test_with_token_and_user tests/unit_tests/plugin_tests/test_github.py::TestGetRepoUrls::test_with_students tests/unit_tests/plugin_tests/test_github.py::TestOpenIssue::test_on_existing_repos tests/unit_tests/plugin_tests/test_github.py::TestOpenIssue::test_on_some_non_existing_repos tests/unit_tests/plugin_tests/test_github.py::TestOpenIssue::test_no_crash_when_no_repos_are_found tests/unit_tests/plugin_tests/test_github.py::TestCloseIssue::test_closes_correct_issues tests/unit_tests/plugin_tests/test_github.py::TestCloseIssue::test_no_crash_if_no_repos_found tests/unit_tests/plugin_tests/test_github.py::TestCloseIssue::test_no_crash_if_no_issues_found tests/unit_tests/plugin_tests/test_github.py::TestGetIssues::test_get_all_open_issues tests/unit_tests/plugin_tests/test_github.py::TestGetIssues::test_get_all_closed_issues tests/unit_tests/plugin_tests/test_github.py::TestGetIssues::test_get_issues_when_one_repo_doesnt_exist tests/unit_tests/plugin_tests/test_github.py::TestGetIssues::test_get_open_issues_by_regex tests/unit_tests/plugin_tests/test_github.py::TestAddReposToReviewTeams::test_with_default_issue tests/unit_tests/plugin_tests/test_github.py::TestAddReposToTeams::test_happy_path tests/unit_tests/plugin_tests/test_github.py::TestDeleteTeams::test_delete_non_existing_teams_does_not_crash tests/unit_tests/plugin_tests/test_github.py::TestDeleteTeams::test_delete_existing_teams tests/unit_tests/plugin_tests/test_github.py::TestVerifySettings::test_happy_path tests/unit_tests/plugin_tests/test_github.py::TestVerifySettings::test_empty_token_raises_bad_credentials tests/unit_tests/plugin_tests/test_github.py::TestVerifySettings::test_incorrect_info_raises_not_found_error[get_user] tests/unit_tests/plugin_tests/test_github.py::TestVerifySettings::test_incorrect_info_raises_not_found_error[get_organization] tests/unit_tests/plugin_tests/test_github.py::TestVerifySettings::test_bad_token_scope_raises tests/unit_tests/plugin_tests/test_github.py::TestVerifySettings::test_not_owner_raises tests/unit_tests/plugin_tests/test_github.py::TestVerifySettings::test_raises_unexpected_exception_on_unexpected_status tests/unit_tests/plugin_tests/test_github.py::TestVerifySettings::test_none_user_raises tests/unit_tests/plugin_tests/test_github.py::TestVerifySettings::test_mismatching_user_login_raises tests/unit_tests/plugin_tests/test_github.py::TestGetPeerReviewProgress::test_nothing_returns tests/unit_tests/plugin_tests/test_github.py::TestGetPeerReviewProgress::test_with_review_teams_but_no_repos