Skip to content

Integrations

GitHub SDK: get started

The complete GitHub API through typed application or agent clients

Use an ordinary App, or an Agent when the workload needs agent identity. Alter builds provider requests from a reviewed contract and applies the same connection authorization, policy, approvals, and audit records as raw requests.

Terminal window
npm install @alter-ai/sdk @alter-ai/github
# Python (installs core automatically)
pip install alter-sdk-github

The provider package includes only GitHub types and response schemas and pins its contract version.

Configure GitHub OAuth or store a GitHub personal access token, request the scopes the application needs, and retain each customer’s grant ID after Connect consent or managed-secret grant creation. Alter supplies the credential; it never belongs in operation input.

import { App } from "@alter-ai/sdk";
import { GitHubIntegration } from "@alter-ai/github";
const app = new App({ apiKey: process.env.ALTER_API_KEY! });
try {
const client = new GitHubIntegration(app, { grantId: process.env.GITHUB_GRANT_ID! });
const result = await (await client.licenses.licensesGetAllCommonlyUsed({})).wait();
console.log(result.bodyJson());
} finally {
await app.close();
}
from alter_sdk import App
from alter_sdk_github import GitHubIntegration
async def first_call(api_key: str, grant_id: str):
async with App(api_key=api_key) as app:
client = GitHubIntegration(app, {"grant_id": grant_id})
call = await client.licenses.licenses_get_all_commonly_used({})
result = await call.wait()
return result.body_json()

Contract 2026-11-01 publishes 1,225 operations from GitHub’s official REST API OpenAPI document, using API version 2026-03-10. It adds the self-hosted runner registration, removal and just-in-time config operations and deploy-key creation to contract 2026-10-28, which stays available. The 29 excluded credential-minting and application-management operations are described below. The API reference links every operation to its complete input fields, response models, TypeScript and Python examples, and policy identity. Browse by resource under this provider’s API reference in the Integrations sidebar, or download github.2026-10-28.openapi.json. The Developer Portal provider view and alter integrations operations github --version 2026-10-28 also expose the schemas.

Generated calls pin the Alter contract version. GitHub’s own product, role, scope and subscription requirements still apply. There is no silent version fallback and no automatic write retry or pagination.

Terminal window
alter integrations execute github github.licenses_get_all_commonly_used \
--version 2026-11-01 --grant "$GITHUB_GRANT_ID" --input '{}' --wait

Arguments use native path, query, headers, and body containers. Array query parameters are sent the way the provider’s document declares them: one delimited value where it declares explode: false (or a pipe- or space-delimited style), repeated keys otherwise. SDK methods preserve provider field names, decimal lexemes and large integers as strings when necessary. HTTP 204 returns null / None from the typed decoder. Binary responses use bodyBytes() / body_bytes(); the CLI can save them with --output-file.

A policy rule can require approval for any operation. The call returns a pending approval; wait() resolves once the approver decides, and resume(approvalId) picks a pending approval up after a restart. Approval cards show the operation, its contract version and the request input the sensitivity review marked safe to display.

repos.reposUploadReleaseAsset / repos.repos_upload_release_asset sends a body object containing filename, content_type, and content_base64. Alter sends the decoded bytes to GitHub’s documented uploads.github.com origin. The connection’s allowed hosts must include that host. The serialized operation input must fit the shared 5 MiB request limit. Raw Markdown uses a string body; HTML and other non-JSON responses use bodyBytes() / body_bytes().

Binary assets, encrypted secret values, webhook secrets/passwords, import passwords, package-restore tokens, deployment OIDC tokens, SARIF uploads and opaque workflow inputs cannot be retained for approval. An immediately authorized operation can still send them. Repository and gist source text follows the existing opaque-text approval behavior; callers must not embed credentials in source.

New operations classify security settings, permissions, webhooks and secret management as admin. Billing budgets, subscription seats, paid runner capacity, and creating, starting or resizing a codespace also carry payment. Invitations, webhook deliveries and pings, and review requests carry send; comments and issue edits that only notify watchers stay write, like the existing issue, comment and pull-request operations. Existing cataloged operations retain their attested families and operation IDs. Payload capture follows the application’s capture setting, on managed and raw proxied calls alike: credentials are removed, the reviewed sensitive fields are masked in requests and responses, and binary bodies, calls that can return a credential and calls carrying raw card data are never stored.

The four ruleset writes (create and update, for a repository or an organization) expose the ruleset’s name, enforcement level, bypass actors, rule types and targeting conditions as policy parameters, on managed and OAuth connections alike, so a rule can allow a rename while requiring approval for a bypass-list change. A parameter rule on these four operations now refuses a request whose body carries a top-level key GitHub does not document for it; to recover, remove the extra key from the request or drop the parameter condition from the rule. The parameter names and example rules are in the GitHub provider reference.

The four secret-scanning alert operations (list for an organization, list for a repository, get and update an alert) return the leaked secret itself, so they are refused by default with credential_minting_refused, on raw proxy calls as well as SDK calls. Raw calls to these routes on existing GitHub connections were previously forwarded. To restore them, an operator adds a credential_minting allowance naming provider github and the operation. Adding an SSH authentication key works like a login for the user, so raw calls that add one are refused the same way. A deploy key reaches only one repository, so adding one is allowed, as is a GPG or SSH signing key, which grants no access.

A require_approval rule now also applies the sensitivity review to raw GitHub proxy calls: a raw request whose body carries a field listed above (for example an encrypted secret value or a webhook secret) is held encrypted with the pending approval and shown masked to the approver, then sent exactly as it was requested once approved. The held copy is deleted after it runs or expires.

Installation access tokens, SSH authentication-key creation, app-manifest conversion and OAuth token reset/scoping are explicitly denied by policy. None of these are SDK methods. Runner registration and removal tokens, just-in-time runner configs and deploy-key creation are narrow-job secrets: they are SDK methods from contract 2026-11-01, allowed on SDK and raw proxy calls, and Alter never stores a runner token or config in a captured payload. Application management and Marketplace seller endpoints that require a GitHub App JWT or client-secret Basic authentication are also excluded: the supported connections supply a user OAuth token or PAT.

The packages target GitHub.com, not GitHub Enterprise Server or GraphQL. GitHub enforces the connection token’s native permissions. The existing OAuth scope model remains in force; narrowing a grant does not turn fine-grained PAT permission names into OAuth scopes. Operations with resource-dependent scope requirements can be refused on narrowed grants unless the existing restriction policy can govern them.

Archive/log download endpoints return GitHub’s native redirect response; Alter does not follow it or forward credentials to a new host. Inspect the result status and headers and handle the provider’s documented download URL separately. bodyJson() only decodes successful JSON responses. GitHub REST error statuses remain provider errors; there is no documented generic 2xx fault envelope.

The pinned official source, its hash, the generated methods and the policy mapping are checked together. Scheduled checks save upstream candidates and report additions, removals and schema changes; they never replace a published contract automatically. Existing contract versions remain available for installed SDKs and pending approvals.

Persist call.approvalId (TypeScript) or call.approval_id (Python), then construct a fresh provider client and call resume(savedId), followed by wait(). The stored approval selects the operation; this installed package verifies its provider and contract version before attaching the response validator. Mismatches raise ManagedOperationError, never silently decode using another contract. See persist-and-resume examples.

Policy operation fields also accept the published SDK function IDs listed by alter integrations operations github. Use when.operation for a json_match or conditional require_approval rule, or match.operations for content_match (including redaction and step-up). Conditional approval can also use when.match.operations with parameter conditions. alter policy simulate --operation <function-id> tests that exact function.

Managed calls carry a server-verified function identity. Alter still evaluates policy against the actual method, URL and body after building the request from the authorized connection. Existing endpoint, method, host, catalog-operation and family rules continue to apply unchanged. A raw call can share an endpoint with several SDK functions and matches all of them; a function name never grants permission or bypasses existing restrictions.

For example, this rule requires approval for one function:

{
"effect": "require_approval",
"when": { "operation": "github.issues_create" },
"approval": { "approvers": ["reviewer@example.com"] }
}

Save it with alter policy rules create --app <app-id> --grant <grant-id> --type require_approval --body @rule.json, or select the function in the portal.

The pinned upstream inventory retains six retired Classroom routes whose only documented response is 410 Gone. Their methods preserve that native failure; they do not restore the retired service.

The typed GitHub packages remain REST-only. Calls through the core SDK proxy to https://api.github.com/graphql and an authorized Enterprise Server’s /api/graphql support root-level policies for OAuth and personal-access-token connections: for example query.repository and mutation.deleteIssue. The operation picker and CLI expose the same identities.

A delete deny permits a read and blocks a deletion, including one embedded in a compound document. Creating or editing an issue, adding an issue comment and creating a pull request carry write, matching their REST twins. Ordinary comments, review text, and discussion and project-status changes also carry write; subscriber notifications or mentions do not add send. Invitations, review requests, marking a draft ready for code-owner review, and assigning people (a nonempty assignee list, which notifies the assignees) carry send, as do a ruleset’s required reviewers and an environment’s deployment reviewers, which choose who is asked to review. Submitting a pull request review (submitPullRequestReview, or addPullRequestReview with an event) publishes it to the pull request and carries send; a review added without an event stays pending and is write. Sponsorship changes carry payment, and administration changes carry admin. updateRef includes the delete capability in discovery; on a request it carries delete only when input.force permits a history rewrite. A false or omitted flag retains write without delete.

updatePullRequestBranch carries delete for history-rewriting REBASE; MERGE and omission retain write. Use an operation rule to govern all branch updates.

Replacing assignees with an empty list is write; a nonempty list, and review requests, also carry send. Clearing or deleting an issue field value (updateIssue with the CLEAR or REMOVE operation, or delete: true on the field-value operations) carries delete. Dedicated removal operations such as closeIssue, closePullRequest, unpinning a comment or clearing all label relationships always carry delete. Locking a conversation carries delete and unlocking it is write, on both REST (issues/lock, issues/unlock) and GraphQL (lockLockable, unlockLockable). Update operations carry delete only for destructive argument values: closing through updateIssue, updatePullRequest or a project update, archiving cards, disabling a ruleset, and turning off a protection (webCommitSignoffRequired, preventSelfReview, a ruleset’s or branch protection rule’s review requirements, or a members-can-create repository type set to false). A ruleset update also carries delete when it switches enforcement to EVALUATE or turns off the extra approval for unattributed changes, and creating or updating a ruleset carries it for dismissStaleReviewsOnPush: true or a nonempty ignoredFilePaths exemption. Replacing a ruleset’s rules, including with an empty rules: [] list, is write; ordinary updates remain writes.

Enterprise SSO recovery codes are refused when selected. An explicit credential_minting allowance for the selected root operation permits that selection; other deny rules still apply, and capture remains withheld. Temporary repository clone tokens are allowed under ordinary policy rules and masked in captured responses, including aliases and fragments. Migration credentials and invitation tokens are masked during approval and withheld from payload capture.

2026-11-01: GraphQL policy classification preserves stored REST operation rules through compatibility aliases, including published SDK function IDs. For example, mutation.mergePullRequest also matches pulls/merge, deleteRef matches git/delete-ref, and createPullRequest matches pulls/create. REST deny and approval rules without parameter conditions cover GraphQL selections, including nested reads in mutation results. Operation allowlists admit an exact GraphQL ID or every family the call carries; pulls/merge never authorizes GraphQL. Use mutation.mergePullRequest or the applicable families. Parameter-scoped REST rules project repos/get parameters owner and repo from query.repository(owner:, name:), users/get-by-username.username from query.user(login:), and orgs/get.org from query.organization(login:). Mutation inputs containing opaque node IDs cannot reconstruct REST path parameters such as owner, repo, issue_number or pull_number. A rule on a related mutation with one of those unprojectable parameters fails closed, as does a related read root without the argument (query.viewer returns the User that users/get-by-username reads); an unrelated root does not match. Unmapped REST identities produce a warning when a rule is saved in the CLI or dashboard. No stored rule rewrite is needed. Rules stored before opt-in retain their previous unclassified, fail-closed GraphQL decisions. New rules use the reviewed aliases and can name the GraphQL root directly for narrower coverage. Changing an existing rule’s body adopts the current per-operation semantics; re-applying an identical body or changing only its name or description preserves its stored semantics.

Full POST JSON documents admit query, variables, operationName and inert extensions; other envelope keys require a documented provider registration. Alternate document selectors (documentId, id, doc_id, or extensions.persistedQuery) are uninspectable even alongside query text; operation/family-aware rules fail closed. Parser safety limits are 500 roots, 30,000 tokens, 64 nesting levels and 512 KiB of query text; the overall body and expanded variables remain bounded at 5 MiB. Split larger documents into calls. Multiple operations require operationName; missing documents and GET/query parameter transport cannot be inspected through this POST endpoint. Standard schema introspection is allowed under ordinary read policies.

Unknown roots and uninspectable shapes remain unclassified; with operation- or family-aware rules policy fails closed on them. This includes unknown mutations, unreadable documents, persisted selectors, GET/query transport and unsupported relay/node re-entry. With no such rules, a request Alter read in full (unknown mutations, relay/node re-entry, a GET carrying only the document parameters) passes through to GitHub. Because the GraphQL endpoint can return a credential, Alter forwards a request without rules only when it has read the whole request: a UTF-8 JSON request object or batch, an application/graphql document, or a GET whose URL carries only query, variables, operationName and extensions. Anything else is refused with credential_minting_refused even when its document is harmless, and no allowance lifts it: form, multipart or compressed bodies, other character sets or invalid UTF-8, persisted-query references without query text, other or repeated URL parameters, and documents that do not parse. An upload sent to the GraphQL endpoint is refused with proxy_body_uninspectable. Readable JSON batch members are inspected individually. A batch of read-only viewer queries passes a delete-family deny rule; a member that matches the deny, or an unknown or unreadable member under an operation/family-aware rule, refuses the whole batch. Inspection does not promise that GitHub accepts the batch transport. Known credential-minting operations remain refused even without rules. Documents or batches too large to complete the credential scan are also refused on a credential-capable endpoint without rules; split them into inspectable calls. Sensitive- output name checks remain active, and drift metrics/alerts and the daily watch report new fields for review. Use ordinary top-level roots and inspectable POST JSON to make operation-aware policies enforceable.

GitHub Enterprise Server uses the pinned GitHub.com schema. Version-specific or removed GHES roots absent from that snapshot follow the same rule-scoped behavior. This does not widen connection host restrictions or add GHES support to the typed REST packages.

Report an issue with this page

Necessary

Required for sign-in, security, authorization, and remembering your choices.

Always active

Analytics

Helps us understand which product and documentation features are useful.

Performance diagnostics

Uses performance tracing and privacy-masked session replay to diagnose problems.

You can change these choices at any time from Cookie settings.