Skip to content

Connect a third-party integration

Wire a CRM, helpdesk, or any HTTP service into your call flows. Two paths — typed integration specs or one-off httpCall nodes.

hey-quad has two ways to talk to third-party services from a call flow:

  • Integrations — typed, audited, reusable specs (HubSpot, Pipedrive, Slack, etc.). Use these when there's a known operation you want to call repeatedly.
  • HTTP call — one-off requests to any URL. Use this when authoring a typed spec is overkill or the service doesn't have one yet.

This article covers the typed integration path. For one-offs, see Call any HTTP endpoint.

Prereqs

You need an API key, OAuth token, or whatever credential the third party requires. hey-quad encrypts these at rest and never shows them in flow logs.

1. Create a connection

Open Settings → Integrations and pick the integration you want. Click New connection, give it a name (e.g. "Production CRM"), and paste the credential fields the spec asks for.

Each connection is org-scoped and can be referenced by any flow in that org via the Integration node.

2. Drop an Integration node into your flow

In the flow editor, drag in Integration. The inspector asks for:

  • Integration — the slug (e.g. hubspot).
  • Operation — which API call to make (e.g. lookupContact).
  • Connection — which credential to use.
  • Inputs — fields driven by the operation's spec, with template support against {{vars.x}}, {{event.from}}, etc.
  • Output mapping — how the response gets stashed back onto vars.

The inputs form is rendered from the operation's inputSchema — every spec is typed, so authoring an integration call doesn't require remembering arbitrary field names.

3. Branch on the result

Integrations write vars.integrationStatus (numeric HTTP-like status) and vars.integrationOk (boolean) on completion. Wire cases off the integration node to branch:

  • vars.integrationOk == true → continue with the lookup result
  • vars.integrationOk == false → play a fallback prompt or transfer to a human

You can also set onError to 'fail' (stop the flow), 'continue' (treat failures as successes — no special branch), or 'route' (emits cases on vars.integrationStatus for finer-grained handling).

What's protected automatically

  • SSRF guard — the runtime refuses calls to private IPs (10.0.0.0/8, 127.0.0.1, 169.254.169.254, etc.) so a misconfigured URL can't pivot inside our infrastructure.
  • Secret redaction — credential values are pulled from the encrypted integration_secrets table at request time and redacted from telemetry. Even if you log the response, secrets won't appear in flow run history.
  • Rate limiting — each connection has a default rate limit so a hot loop in a flow can't burst-spam a third party.
  • Audit trail — every integration call writes a row to integration_runs with the inputs (templated values resolved) and the redacted response.

Common gotchas

  • Integration operations are pinned by version. Republishing a spec with a breaking change doesn't silently re-route live flows — they keep using the version they were saved against. Bump the spec version, then explicitly opt flows in.
  • vars.integrationStatus is numeric, not string. Branch with == against a number, not a quoted string.
  • Response redaction shows up downstream. If a templated field happens to equal a secret value, the redacted marker appears in vars.<responseVar> and any downstream prompt would render it. Don't template prompts directly off raw integration responses without sanitising.