Repository navigation
Allow configuring a custom API endpoint per host #13717
Description
Describe the feature or problem you'd like to solve
gh lets you configure which GitHub host to use, but the API endpoint is always derived from that host — there's no way to route API traffic to a different endpoint.
Virtually every other tool in the GitHub ecosystem already treats the API endpoint as a separate configuration:
- GitHub Actions —
GITHUB_API_URLis independent fromGITHUB_SERVER_URL - Octokit JS —
baseUrloption - Octokit Ruby —
api_endpointoption - PyGithub —
base_urlparameter - go-github —
NewEnterpriseClient()
gh is the last commonly used tool in the ecosystem that doesn't let you configure where API requests go.
This matters in practice when an organization runs an API gateway or reverse proxy in front of GitHub — for access logging, rate-limit visibility, or request-level monitoring. Web UI and git clone/push traffic can stay on the canonical hostname (OAuth/SSO callbacks are host-bound, and git remotes work as-is), but API traffic is machine-to-machine and can be routed through a different endpoint. Every API client can be pointed at the gateway except gh.
It's especially relevant for GHEC data-residency tenants, where the *.ghe.com DNS zone is GitHub-managed and the organization has no control over the api.* hostname — routing API calls through a different endpoint is the only option, and gh doesn't support it.
Proposed solution
Add an optional API endpoint override to the per-host configuration in hosts.yml:
example.ghe.com:
user: pete
api_host: api-gateway.example.netWhen set, gh sends REST and GraphQL requests to that host instead of the derived default. Authentication is unchanged. When not set, behavior is identical to today.
Additional context
Workarounds that people try today don't hold up:
git config url.*.insteadOf— only applies to git transport;gh's API HTTP client doesn't read it (see #12916)- Forking
gh— works but means tracking every upstream release indefinitely across all platforms
The derivation logic lives in internal/ghinstance/host.go (RESTPrefix, GraphQLEndpoint) — the change seems contained. The api_host field above is one possible shape; we're open to whatever approach fits gh's config model best as long as there's a way to route API traffic to a different endpoint. We use gh at scale and are happy to contribute a PR if the maintainers are on board with the direction.
Activity
babakks commentedon Jun 24, 2026
Thanks for your feedback, @dziemba! 🙏
Providing a way for mapping hostnames has been under our radar somehow. Recently we opened #12928, to explore an env var based approach for granular token selection. However, what you're suggesting here kind of falls into the same concept. So, I encourage you to have a read at #12928 and share your thoughts with us.
Note
I know what you're suggesting here is more about a configuration option, but config vs env var is just a matter of exposure of a functionality. The best for
ghis to offer them equally as each serve a different class of use cases (e.g. env vars tend to be more favourable in automated environments/infrastructure, while configuration is more appealing to human users).@BagToad and I had a quick chat and we're ideating about expanding the env vars in #12928 to allow overriding base API URLs as well:
This is not exactly a mapping approach, mostly because
ghdoesn't really need to know the exact target hostname (i.e.example.ghe.com), but I believe this would serve your use case.For your scenario, I can imagine you'd just need to populate
GH_API_URL_*andGH_HOST_TYPE_*, and the token selection would be left to theghcredential selection mechanism.Feel free to comment your thoughts, @BagToad and @dziemba.
dziemba commentedon Jun 25, 2026
Thanks for the quick reply. I'm glad you're interested in this idea!
This looks great and combines this request nicely with #12928. I believe it would solve our use-case.
Ideally we'd also have the
hosts.yamloption in addition to the env overrides. In some environments, especially developer laptops, it would be easier to just set the overrides once in the file, instead of having to ensure that the environment variable overrides propagate everywhere (e.g. different shell setups, AI coding tools, IDEs etc.).github-actions commentedon Jun 29, 2026
Thank you for your issue! We have categorized it as an enhancement (feature or improvement) request, and it has been added to our backlog. In doing so, we are not committing to implementing this feature at this time, but, we will consider it for future releases based on community feedback and our own product roadmap.
Unless you see the help wantedContributions welcome
label, we are not currently looking for external contributions for this feature.
If you come across this issue and would like to see it implemented, please add a thumbs up! This will help us prioritize the feature. Please only comment if you have additional information or viewpoints to contribute.
Add api_host config for custom API endpoint routing
Add api_host config for custom API endpoint routing
Add api_host config for custom API endpoint routing
feat(config): add api_host for custom API endpoint routing
feat(config): add api_host for custom API endpoint routing
feat(config): add api_host for custom API endpoint routing
williammartin commentedon Jul 22, 2026
@dziemba one thing that's not clear to me in your setup (as per the PR you opened) is how you expect to handle URLs in http response headers or bodies. For example, given a GHEC deployment at
company.ghe.comwhich you want to gateway atgithub.company.com, by default, URLs are going to point tocompany.ghe.com. A specific example would be pagination, which includesLinkheaders in the http response.It seems to me there are three ways this might be solved:
github.company.comFrom your PR it seems like maybe the last point is what you're expecting but it seems like a lot of work to put on downstream consumers of your gateway. Maybe we're the only one? Am I understanding this correctly? Cheers.
dziemba commentedon Jul 23, 2026
Hey @williammartin
AFAIK GHEC does not allow custom domains and has no way of rewriting URLs internally.
We have solved this in our company by having the gateway rewrite URLs, both in Link headers and in the JSON responses. It was a bit tricky to get right but works perfectly fine now.
So we would not expect the
ghCLI to rewrite the URLs itself.davidlin-stripe commentedon Jul 28, 2026
Hi!
Thank you for proposing this, we've had similar issue before and the solution is largely identical to what we have here. Although, would it be worth consolidating this implementation to
go-gh?In the case where user install custom extensions, for example gh-stack, we'll face this issue again, as it uses the HTTP client from the go-gh library, and just eye-balling from the implementation it seems to be farily close to the one hand-rolled in cli. But this implies a larger refactor on the cli, which might not be worth it.
williammartin commentedon Jul 28, 2026
Hey @davidlin-stripe, thanks for dropping by.
Yep, 100%. That's one of my biggest concerns with the linked PR. I have this loose plan to consolidate API Client usage, which should then allow me to push API host mapping down into
go-ghso that extensions can make use of it.williammartin commentedon Aug 7, 2026
@dziemba @davidlin-stripe I am heading out on vacation for two weeks but I believe I have an artifact that y'all can play around with that is addressing most use cases. Specifically called out as not done yet are:
gh csthough it already supportsGITHUB_API_URLgh set configorgh auth login --api-hostgh auth statusThis Pull Request is really focused on migrating everything into a shared place that will respect this config. It's the big lift after the easy ones in:
It absolutely requires more review and more poking at from me, but I really wanted to get something in your hands before I head out. I've been banging my head against it for a week now so you may find something sus in there, but I believe it's sufficient for you to get and play around with, to make sure it works as you expect, or to leave review comments on places that don't (after all, you have very bespoke setups).
Quick demo
Needs Go 1.26+ and
make. This buildsghfrom the pull request and points it at your gateway using a throwaway config directory, so your realghsetup is untouched.Should look like:
Which demonstrates a few different paths that are correctly respecting
api_host. Of course, it would be awesome if you could make the change in your own environments and see that it works correctly.Examples
GHEC (ish)
First, with no
api_hostkey:Then with an
api_hostkey:GHES
First, with no
api_hostkey:Then with an
api_hostkey:Note that the
api_hostis a direct swap in theHostheader, it's not trying to infer subdomain or path suffixes. I could imagine, particularly in the GHES case that it might be nice to drop the path.Cheers, and see you in a couple of weeks. Feel free to reach out to @babakks or @BagToad here in my absence.