Layers
Partner APIAPI referenceGitHub

POST /v1/github/installation

Bind a GitHub App installation ID to your Layers organization.

View as Markdown
POST/v1/github/installation
Phase 1stable
Auth
Bearer
Scope
github:admin

Record the GitHub App installation your user just authorized. Layers uses this binding to create short-lived tokens for cloning, analyzing, and opening PRs against any repo the install can see. One installation per organization.

The installation flow is: you send the user to a Layers install URL (GET /v1/github/installation/install-url), GitHub redirects back to you with an installation_id in the query string, you post that ID here. One uninstall on the GitHub side revokes all access — the API does not store long-lived GitHub credentials.

Body
  • installationId
    integerrequired
    The numeric `installation_id` GitHub returned on the redirect.
  • state
    stringrequired
    The CSRF `state` value GitHub round-tripped on the redirect — same string you originally sent (or that Layers generated) on `/install-url`.

The body is strict — extra keys (e.g. orgLogin, note) are rejected with 422 VALIDATION. The org login is read from GitHub via the installation itself and returned in the response.

Example request

curl https://api.layers.com/v1/github/installation \
  -H "Authorization: Bearer lp_live_01HX9Y6K7EJ4T2_4QZpN..." \
  -H "Content-Type: application/json" \
  -d '{
    "installationId": 50291845,
    "state": "lUNN5tIRm-K3a8sBXvBQDxVOCgz2x9YK"
  }'
await layers.github.registerInstallation({
  installationId: 50291845,
  state: "lUNN5tIRm-K3a8sBXvBQDxVOCgz2x9YK",
});
layers.github.register_installation(
    installation_id=50291845,
    state="lUNN5tIRm-K3a8sBXvBQDxVOCgz2x9YK",
)

Response

201Created
{
  "installationId": 50291845,
  "githubAccount": {
    "login": "acme-coffee",
    "type": "Organization"
  },
  "orgLogin": "acme-coffee",
  "status": "active",
  "registeredAt": "2026-04-18T19:14:09.123456+00:00"
}

Re-posting the same installationId for an org that's already bound to it is a no-op — registeredAt reflects the original grant.

Errors

StatusCodeWhen
422VALIDATIONinstallationId / state missing, unknown body keys supplied, or GitHub reports the installation does not exist / the App cannot see it.
401UNAUTHENTICATEDMissing or invalid key.
403FORBIDDEN_SCOPEKey lacks github:admin.
409CONFLICTYour organization already has a different installation bound. Detach first.
429RATE_LIMITEDWrite budget exhausted.

See also

On this page