GitHub Public API Limitations
GitHub Public API Limitations
This issue collates all of the feature gaps within the public GitHub REST API and GitHub GraphQL API
[!NOTE] See GitHub API Changelog for new feature announcements See GitHub Public Roadmap for planned upcoming features
[!IMPORTANT] Filter issues by github-api-limitation to see full backlog
GitHub REST API - Documentation
- List Notifications endpoint
/notifications- Filtering capabilities
- No query parameter to filter notifications by inbox
- No query parameter to filter notifications by saved
- No query parameter to filter notifications by done
- Response schema
- No attribute in response indicating if a notification is done, saved or in the inbox.
- Notifications of subject.type
CheckSuite,RepositoryInvitationorWorkflowRunalways have null forsubject.urlandsubject.latest_comment_url - Notifications of subject.type
Discussionreturn forsubject.url/subject.latest_comment_urlwhich doesn't point to the latest comment. We have had to implement a fix to find these ourselves. See #1583
- Private repositories Notifications show in UI but not via this API
- Filtering capabilities
- Notification
- No endpoint to mark notification as unread (can only mark a notification as read)
- No endpoint to find CheckSuite of WorkflowRun information by notification_id
- No endpoint to save/unsave a notification
- Authentication
- No support for fine-grained tokens https://github.com/gitify-app/gitify/issues/1492
GitHub GraphQL API - Documentation
- No query to fetch user notifications
- No query to find CheckSuite of WorkflowRun information by notification_id
While it's been a while since I was looking at it, this thread for adding support to view notifications to the gh CLI might have some pointers towards API workarounds, eg:
- https://github.com/cli/cli/issues/659#issuecomment-1485939570
-
IIRC you cannot mark notifications as Done, just Read
-
A little light reverse engineering seems to show that the webpage makes a call to
/notifications/beta/archivewhen I click the button
-
- https://github.com/cli/cli/issues/659#issuecomment-2599592102
-
Seems like the Mobile app is using some graphQL API endpoints behind a feature flag
-
POST /graphql HTTP/2 Host: api.github.com Content-Type: application/json Graphql-Features: merge_queue,private_profile_setting,project_next_field_configuration,issues_close_state,project_next_recent_connection,file_level_commenting,issue_types,sub_issues Accept: application/vnd.github.merge-info-preview+json,application/vnd.github.shadow-cat-preview+json,application/vnd.github.echo-preview+json,application/vnd.github.starfox-preview+json,application/vnd.github.doctor-strange-preview+json Apollographql-Client-Version: 1.192.0-152022212 Authorization: Bearer REDACTED Accept-Encoding: gzip, deflate, br Accept-Language: en-GB;q=1.0, en-AU;q=0.9, ja-AU;q=0.8, fa-AU;q=0.7 Content-Length: 4030 User-Agent: GitHub/1.192.0 (com.github.stormbreaker.prod; build:152022212; iOS 18.2.1; iPhone15,3) X-Apollo-Operation-Type: query Apollographql-Client-Name: com.github.stormbreaker.prod-apollo-ios X-Apollo-Operation-Name: Inbox { "operationName": "Inbox", "query": "query Inbox($first: Int!, $after: String, $filterBy: NotificationThreadFilters, $query: String, $avatarSize: Int!) { viewer { __typename id ...WebNotificationsEnabledFragment notificationThreads( first: $first after: $after filterBy: $filterBy query: $query ) { __typename pageInfo { __typename hasNextPage endCursor } totalCount nodes { __typename ...NotificationThreadCommonFieldsFragment url subject { __typename ... on CheckSuite { ...InboxSubjectCheckSuiteFieldsFragment } ... on WorkflowRun { ...InboxSubjectWorkflowRunFieldsFragment } ... on Commit { ...InboxSubjectCommitFieldsFragment } ... on Gist { ...InboxSubjectGistFieldsFragment } ... on TeamDiscussion { ...InboxSubjectTeamDiscussionFieldsFragment } ... on Issue { ...InboxSubjectIssueFieldsFragment } ... on PullRequest { ...InboxSubjectPullRequestFieldsFragment } ... on Release { ...InboxSubjectReleaseFieldsFragment } ... on RepositoryVulnerabilityAlert { ...InboxSubjectRepositoryVulnerabilityAlertFieldsFragment } ... on RepositoryAdvisory { ...InboxSubjectRepositoryAdvisoryFieldsFragment } ...InboxSubjectDiscussionFieldsFragment ... on RepositoryDependabotAlertsThread { ...InboxSubjectRepositoryDependabotAlertsThreadFieldsFragment } ... on SecurityAdvisory { ...InboxSubjectSecurityAdvisoryFieldsFragment } } } } } }\nfragment AvatarFragment on Actor { __typename avatarUrl(size: $avatarSize) }\nfragment InboxSubjectCheckSuiteFieldsFragment on CheckSuite { __typename id url conclusion status }\nfragment InboxSubjectCommitFieldsFragment on Commit { __typename id abbreviatedOid url repository { __typename id owner { __typename id login } name } }\nfragment InboxSubjectDiscussionFieldsFragment on Discussion { __typename id url number discussionStateReason: stateReason answer { __typename id } category { __typename id isAnswerable } repository { __typename id isOrganizationDiscussionRepository } }\nfragment InboxSubjectGistFieldsFragment on Gist { __typename url id }\nfragment InboxSubjectIssueFieldsFragment on Issue { __typename id number issueState: state stateReason issueHtmlTitle: titleHTML url }\nfragment InboxSubjectPullRequestFieldsFragment on PullRequest { __typename id number pullRequestHtmlTitle: titleHTML url ...PullRequestStateIcon }\nfragment InboxSubjectReleaseFieldsFragment on Release { __typename id tagName url }\nfragment InboxSubjectRepositoryAdvisoryFieldsFragment on RepositoryAdvisory { __typename id url }\nfragment InboxSubjectRepositoryDependabotAlertsThreadFieldsFragment on RepositoryDependabotAlertsThread { __typename id notificationsPermalink }\nfragment InboxSubjectRepositoryVulnerabilityAlertFieldsFragment on RepositoryVulnerabilityAlert { __typename id permalink }\nfragment InboxSubjectSecurityAdvisoryFieldsFragment on SecurityAdvisory { __typename id ghsaId notificationsPermalink }\nfragment InboxSubjectTeamDiscussionFieldsFragment on TeamDiscussion { __typename url id }\nfragment InboxSubjectWorkflowRunFieldsFragment on WorkflowRun { __typename id url runNumber workflow { __typename id name } checkSuite { __typename id } }\nfragment ListSubscribableFragment on Subscribable { __typename id viewerSubscription viewerCanSubscribe }\nfragment NotificationThreadCommonFieldsFragment on NotificationThread { __typename id threadType title isUnread unreadItemsCount lastUpdatedAt subscriptionStatus summaryItemAuthor { __typename id ...AvatarFragment } summaryItemBody isArchived isSaved reason list { __typename ...ListSubscribableFragment ... on Repository { id owner { __typename id login } name } ... on User { id login userName: name } ... on Team { id organization { __typename id login } slug } ... on Organization { id login } } }\nfragment PullRequestStateIcon on PullRequest { __typename pullRequestState: state isDraft mergeQueueEntry { __typename id position } }\nfragment WebNotificationsEnabledFragment on User { __typename notificationSettings { __typename getsParticipatingWeb getsWatchingWeb } }", "variables": { "avatarSize": 48, "first": 30, "query": "" } } - And then if I click on a filter tab in the iOS app like 'unread' it changes
querytois:unread; saved isis:saved, done isis:done, etc - Mark notification as 'undone':
-
POST /graphql HTTP/1.1 Host: api.github.com GraphQL-Features: merge_queue,private_profile_setting,project_next_field_configuration,issues_close_state,project_next_recent_connection,file_level_commenting,issue_types,sub_issues Authorization: Bearer gho_REDACTED Accept: multipart/mixed;deferSpec=20220824,application/graphql-response+json,application/json,application/vnd.github.merge-info-preview+json,application/vnd.github.shadow-cat-preview+json,application/vnd.github.echo-preview+json,application/vnd.github.starfox-preview+json,application/vnd.github.doctor-strange-preview+json apollographql-client-version: 1.222.0-170680083 Accept-Language: en-GB;q=1.0, en-AU;q=0.9, ja-AU;q=0.8, fa-AU;q=0.7 Accept-Encoding: br;q=1.0, gzip;q=0.9, deflate;q=0.8 Content-Type: application/json Content-Length: 265 User-Agent: GitHub/1.222.0 (com.github.stormbreaker.prod; build:170680083; iOS 18.6.0; iPhone15,3) X-APOLLO-OPERATION-TYPE: mutation apollographql-client-name: com.github.stormbreaker.prod-apollo-ios Connection: keep-alive X-APOLLO-OPERATION-NAME: MarkNotificationAsUndone { "operationName": "MarkNotificationAsUndone", "query": "mutation MarkNotificationAsUndone($notificationId: ID!) { markNotificationAsUndone(input: { id: $notificationId }) { __typename success } }", "variables": { "notificationId": "NT_kwDOAAuA47E4ODcxMjU0MzkzOjc1Mzg5MQ" } }
-
- Save/unsave/view saved: https://github.com/gitify-app/gitify/issues/840#issuecomment-3208846701
-
Some of the private APIs used on https://github.com/notifications (though likely less useful as they use authenticity_token to prevent CSRF:
- mark as read:
POST https://github.com/notifications/beta/markMIME Type: multipart/form-data-
------WebKitFormBoundaryLqH0emMzDeIcrXrh Content-Disposition: form-data; name="authenticity_token" REDACTED ------WebKitFormBoundaryLqH0emMzDeIcrXrh Content-Disposition: form-data; name="notification_ids[]" NT_kwDOAAuA47IxODEzREDACTED ------WebKitFormBoundaryLqH0emMzDeIcrXrh Content-Disposition: form-data; name="notification_ids[]" NT_kwDOAAuA47IxODM0REDACTED ------WebKitFormBoundaryLqH0emMzDeIcrXrh--
- mark as unread:
POST https://github.com/notifications/beta/unmarkMIME Type: multipart/form-data-
------WebKitFormBoundaryBWyAgv8M6HPBkTAX Content-Disposition: form-data; name="authenticity_token" REDACTED ------WebKitFormBoundaryBWyAgv8M6HPBkTAX Content-Disposition: form-data; name="notification_ids[]" NT_kwDOAAuA47IxODEzREDACTED ------WebKitFormBoundaryBWyAgv8M6HPBkTAX Content-Disposition: form-data; name="notification_ids[]" NT_kwDOAAuA47IxODM0REDACTED ------WebKitFormBoundaryBWyAgv8M6HPBkTAX--
- mark as done / archive:
POST https://github.com/notifications/beta/archiveMIME Type: multipart/form-data-
------WebKitFormBoundary1RpEegHaXAmtMNxM Content-Disposition: form-data; name="authenticity_token" REDACTED ------WebKitFormBoundary1RpEegHaXAmtMNxM Content-Disposition: form-data; name="notification_ids[]" NT_kwDOAAuA47IxODEzREDACTED ------WebKitFormBoundary1RpEegHaXAmtMNxM Content-Disposition: form-data; name="notification_ids[]" NT_kwDOAAuA47IxODM0REDACTED ------WebKitFormBoundary1RpEegHaXAmtMNxM--