The GitHub integration syncs organization membership data into ZombieLicenseHunter. It connects as a GitHub App that you create and install on your organization: short-lived installation tokens are minted from a JWT signed with the app's private key, so no browser redirect and no personal token are involved.
Prerequisites
- A GitHub organization that you administer.
- A GitHub App installed on that organization with the Organization permissions → Members: Read permission.
- The app's App ID, the Installation ID for your organization, and an RSA private key generated for the app.
Setup Instructions
Step 1: Create and install a GitHub App
- In GitHub, open your organization's Settings → Developer settings → GitHub Apps and click New GitHub App.
- Give it a name (e.g.,
ZombieLicenseHunter) and any homepage URL. Leave webhooks disabled; the integration does not use them. - Under Permissions → Organization permissions, set Members to Read-only. No repository permissions are needed.
- Create the app, then on its settings page click Generate a private key. GitHub downloads a
.pemfile — keep it safe, it is the only copy. - Note the App ID shown at the top of the app's settings page.
- Click Install App and install it on your organization. After installing, the browser URL ends in
/installations/<number>; that number is the Installation ID.
Step 2: Connect in ZombieLicenseHunter
- Go to Integrations → Add Integration and select GitHub. Leave Category as Application.
- Enter:
- GitHub Organization — the organization's login name as it appears in its URL (e.g.,
acme-corp) - GitHub App ID — the numeric App ID from Step 1
- GitHub Installation ID — the numeric Installation ID from Step 1
- GitHub Private Key — the full contents of the downloaded
.pemfile, including the-----BEGINand-----ENDlines
- GitHub Organization — the organization's login name as it appears in its URL (e.g.,
- Click Save Integration. ZombieLicenseHunter checks that both IDs are numeric and that the key parses as a PEM RSA private key, then encrypts and stores everything and queues the first sync.
- The first sync signs a JWT with the key and exchanges it for an installation access token. A wrong App ID, Installation ID or key therefore surfaces as a sync error on the integration page, not at save time.
What Gets Synced
Only organization members are synced. Repositories, teams, and audit logs are not included.
For each member, the following fields are collected:
| Field | Notes |
|---|---|
login |
GitHub username |
databaseId |
Stable numeric GitHub user ID |
email |
The member's public profile email, otherwise an email on one of the organization's verified domains, otherwise empty |
Data is fetched via the GitHub GraphQL API with cursor pagination (100 members per page). The sync is rate-limit aware and operates within GitHub's 5,000 requests/hour limit.
Troubleshooting
Save is rejected with "Private key must be in PEM format"
Paste the whole .pem file, including the -----BEGIN RSA PRIVATE KEY----- (or -----BEGIN PRIVATE KEY-----) header and the matching footer.
First sync fails with an authentication error Confirm the App ID and Installation ID belong to the same app and that the app is installed on the organization you entered. Regenerate the private key in the app's settings if in doubt and update it on the integration's edit page.
Sync fails asking for "Organization > Members: Read" The app's organization permission is missing or a permission change has not been accepted. Grant Members: Read-only on the app, then approve the updated permissions under your organization's Settings → GitHub Apps.
No members returned Verify the organization login is spelled exactly as in its URL and that the app installation covers that organization.
Members have empty emails GitHub only exposes a member's email if it is public on their profile or belongs to a domain your organization has verified. Verify your domains under the organization's Settings → Verified and approved domains.