Skip to content

Build your own integration

Integrations

Greenlight does not require a vendor-specific plugin for every upstream. Most well-known services are in the integration catalog — a searchable, logo’d list (GitHub, Slack, OpenAI, Salesforce, Snowflake, Azure SQL, …) that prefills the upstream’s display name, base URL, and auth, and shows IT exactly how to obtain that provider’s credential. Build your own is the Custom path for every HTTP upstream the catalog doesn’t ship: a SaaS API, an internal microservice, a corporate gateway. It opens the same registration wizard with blank fields. (Connected databases register from their catalog entry — see Integrations.)

This page covers the conceptual flow. The step-by-step admin instructions live in Manage integrations.

  • An HTTPS base URL for the upstream service (for an HTTP integration).
  • An authentication mode — a static credential, OAuth client credentials, or user-delegated token exchange.
  • An idea of which apps will use it, since granting is per-app.

A custom integration is registered with a single auth mode that tells Greenlight how to obtain the upstream credential. You pick one; a provider that supports two identity models is registered as two separate integrations — for example salesforce and salesforce-user. See Data brokering and Manage integrations for that rule.

Auth modeWhen to pick it
Service accountThe upstream takes a static credential — an API key, bearer token, or basic auth. This is the common case.
Client credentialsThe upstream issues a token via the standard OAuth client-credentials grant.
User-passthroughThe upstream wants the end user’s identity and enforces that user’s own permissions, via OAuth token exchange.

Picking the right mode is usually a 30-second read of the upstream’s API documentation. For a service account, the registration form also requires one credential placement: an Authorization: Bearer header, HTTP basic auth, a custom header (e.g. X-Api-Key), or a query parameter. Basic auth lets you choose whether the API key is the username or password; the latter also collects the non-secret username. Custom-header and query-parameter choices collect the provider’s field name.

When you register the integration you also choose how the bound credential is delivered:

  • Proxied (the default for HTTP) — the app calls GREENLIGHT_PROXY_URL, sends GREENLIGHT_DATA_KEY where the upstream credential would normally go, and Greenlight swaps in the credential at the request edge. The secret never reaches the app, every call is audited, and rotation takes effect on the next request.
  • Injected — Greenlight injects the credential into the app as an environment variable you name (e.g. MYSERVICE_API_KEY), and the app calls the upstream directly. Use this for anything the proxy can’t carry — for example a request-signing flow an HTTP pass-through can’t handle.

For a proxied integration registered as, say, myservice, the app reaches it through the proxy URL with the integration name as the first path segment. For a bearer-shaped integration:

await fetch(
`${process.env.GREENLIGHT_PROXY_URL}/myservice/v1/widgets`,
{
method: 'GET',
headers: { Authorization: `Bearer ${process.env.GREENLIGHT_DATA_KEY}` },
}
);

If the upstream expects X-Api-Key, the app sends X-Api-Key: process.env.GREENLIGHT_DATA_KEY instead; if it expects ?apikey=, the app uses that query parameter. The broker rewrites the path against the registered base URL and substitutes the credential in the same slot. The app’s code stays portable — it depends on the proxy URL env var, not on the upstream’s hostname, and never holds the credential.

For an injected integration the app reads the env var you named and calls the upstream directly:

const res = await fetch('https://api.myservice.com/v1/widgets', {
headers: { Authorization: `Bearer ${process.env.MYSERVICE_API_KEY}` },
});

A Custom integration starts with no Knowledge entries — its card shows an empty state inviting you to add the first one, just like a catalog registration. You, an app owner, or a builder agent during a real session authors the first entries — a connection overview, idiomatic requests, common errors — so agents building against your upstream have a head start. See Curate knowledge.

Every call through a proxied custom integration is audited identically to a catalog integration:

  • The acting user, when the call is made on behalf of a signed-in user.
  • The app id.
  • The integration name and the upstream URL.
  • The HTTP method and response code.
  • The end-to-end latency.

The audit record does not include request bodies by default. An injected integration calls the upstream directly, so Greenlight doesn’t see those calls — there’s no per-call data-access audit, which is part of the tradeoff of choosing injected over proxied.

Greenlight does not version integration definitions. If you change the base URL, the auth mode, or the credential, the change takes effect on the next call for a proxied integration, or on the app’s next deploy for an injected one. Apps that depend on a breaking change in the upstream see the same kind of breakage they would see directly — the broker is a pass-through for semantics, not a compatibility layer.