Skip to content

Service account integrations

Integrations

A service account integration is the default kind. IT registers an upstream HTTP service in the dashboard, attaches a credential to it, and grants it to apps that need it. Every call from those apps goes through the data broker, which supplies the credential at the request edge.

The upstream system sees one identity — the service account — regardless of which app or end user produced the request. Per-end-user attribution lives in Greenlight’s audit log, not in the upstream system.

Service account integrations cover the majority of internal SaaS and HTTP APIs. They are the right choice when:

  • The upstream system doesn’t natively enforce per-user permissions on its API, or
  • Per-user enforcement isn’t required for the use case, or
  • The integration is fundamentally org-level (a shared Slack workspace, a shared GitHub organization).

If the upstream system does enforce per-user permissions and you want those to apply to Greenlight apps, use User-passthrough integrations instead.

A service account integration uses the service account auth mode: a static credential (an API key, a bearer token, or basic auth) that IT registers once. The auth mode is the single axis that decides how Greenlight obtains the upstream credential — see Data brokering for the full model (the other modes are client credentials and user-passthrough).

Because not every API takes its key in the same place, a service account integration also records where the credential goes on the wire:

PlacementExample upstream
Authorization: Bearer headerMost modern SaaS APIs
HTTP basic authOlder or self-hosted services
A custom header (e.g. X-Api-Key)APIs with their own header convention
A query parameter (e.g. ?apikey=…)A handful of data APIs
Several headers at onceAPIs that split a key id and secret across headers

For a catalog integration, the provider-defined placement is visible at registration but read-only. For a Custom integration, you select one placement and provide any required header, query-parameter, or Basic-username detail. After registration, app code sends GREENLIGHT_DATA_KEY in that same placement, and the broker swaps in the real credential before forwarding — the app never sees it.

Most service account integrations are a one-click pick from the integration catalog — a searchable, logo’d list of curated upstreams. Choosing a catalog entry prefills the display name and base URL, shows the auth mode and wire placement read-only, and explains how to obtain that provider’s credential. Anything the catalog doesn’t cover is a Build your own registration, which opens the same wizard with blank fields. Both paths start with no Knowledge entries; teams author connection notes as they use the integration.

Catalog integrationAuth
SlackWorkspace OAuth install (bot token)
GitHubGitHub App install scoped to an organization
Google WorkspaceDomain-Wide Delegation service account
Close (CRM)API key
FirefliesAPI key
OpenAI, and other HTTP APIsStatic key, in the placement the provider expects

A service account credential reaches the app one of two ways — a per-integration choice IT makes at registration, covered in full under Data brokering:

  • Proxied (the default) — the app calls GREENLIGHT_PROXY_URL, sends GREENLIGHT_DATA_KEY where the provider credential would normally go, and the broker swaps in the credential at the edge. The secret never reaches the app, every call is audited per-user, and rotating the credential takes effect on the next request.
  • Injected — the credential is injected into the app’s environment under a name IT chooses, and the app calls the upstream directly. There’s no per-call audit and rotation needs a redeploy, but it’s the option for credentials an HTTP proxy can’t carry.

The grant model is identical either way; only delivery differs.

For a proxied integration the app code is plain HTTP or normal provider SDK code against the proxy URL. The path after the integration name is forwarded verbatim to the upstream, and the data key goes in the provider’s normal credential slot. For a bearer-shaped integration:

// Post to Slack
await fetch(
`${process.env.GREENLIGHT_PROXY_URL}/slack/api/chat.postMessage`,
{
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.GREENLIGHT_DATA_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ channel: '#alerts', text: 'Build complete' }),
}
);

For an API that expects a custom header, the app uses that header with GREENLIGHT_DATA_KEY; for an API that expects a query parameter, it uses that parameter. The app does not need to know the real workspace token or service credential. The broker handles it.

The IT-admin workflow lives in Manage integrations. Briefly:

  1. Register the integration — pick a catalog entry, or Custom for an uncatalogued service.
  2. Attach a credential (paste a token, complete the install flow, or upload a service-account JSON). Each credential carries a stable slug, a free-text scope, and one setting you control: an approval policy (whether a declared grant takes effect on merge or queues for your review).
  3. Grant the integration to apps that need it.
  4. Rotate the secret when your org’s rotation policy says to — the slug and every grant survive the rotation. A proxied credential picks up the new value on the next call; an injected one takes effect at the app’s next deploy.

To pull one app’s access, revoke its grant on the /permissions page — the app’s next call returns a structured error and the agent surfaces it. Deleting a credential or a whole integration is a guarded action: Greenlight refuses while any app still holds an active grant and tells you which apps to revoke first, so a credential is never pulled out from under a live app.

A granted integration works locally too — an agent’s bundled greenlight CLI can use it while building. For a proxied credential the laptop never holds the secret — greenlight run mints a short-lived, app- and user-scoped token and the app calls the same proxy URL the deployed app uses. For an injected credential the granted developer’s process receives the real value (that is what granting an injected credential means — the dashboard warns you at registration and approval). An agent can also read live results from a granted proxied integration through the always-on inspectIntegrationApi tool, which runs inside the control plane and returns results only — never the credential. No credential value ever passes through the agent. See Build with your agent.