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.
When to use this kind
Section titled “When to use this kind”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.
How the auth mode is set
Section titled “How the auth mode is set”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:
| Placement | Example upstream |
|---|---|
Authorization: Bearer header | Most modern SaaS APIs |
| HTTP basic auth | Older 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 once | APIs 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.
Registering from the catalog
Section titled “Registering from the catalog”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 integration | Auth |
|---|---|
| Slack | Workspace OAuth install (bot token) |
| GitHub | GitHub App install scoped to an organization |
| Google Workspace | Domain-Wide Delegation service account |
| Close (CRM) | API key |
| Fireflies | API key |
| OpenAI, and other HTTP APIs | Static key, in the placement the provider expects |
How the credential reaches the app
Section titled “How the credential reaches the app”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, sendsGREENLIGHT_DATA_KEYwhere 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.
What an app sees (proxied)
Section titled “What an app sees (proxied)”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 Slackawait 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.
Operating a service account integration
Section titled “Operating a service account integration”The IT-admin workflow lives in Manage integrations. Briefly:
- Register the integration — pick a catalog entry, or Custom for an uncatalogued service.
- 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).
- Grant the integration to apps that need it.
- 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.
Local development
Section titled “Local development”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.