# Ask Immiscible before acting, from any agent builder

> The decision API is published as OpenAPI 3.1 at /openapi.json, with a 3.0 copy and a Power Platform connector. Import it as an action, or connect a builder to the MCP server, so the agents people build without code ask before they pay, share data or act.

Source: https://immiscible.fly.dev/docs/guides/openapi-actions

More and more agents are built in tools rather than code: Copilot Studio, ChatGPT, Agentforce, n8n, Zapier, Make, Lindy, Relevance AI. Each of them can call an outside service before an agent acts. This page says which way in each one offers, and what to import.

> **Note**
> Names describe what each integration does. None of these companies endorses or partners with Immiscible.

## The four operations

Every route below already exists; the OpenAPI file describes them so a builder can import them as actions.

| Operation | Route | What it does |
|---|---|---|
| `requestDecision` | `POST /v1/actions/authorize` | Ask before acting. The answer is `allow` with a signed receipt, `deny` with reasons, or `approval_required` |
| `getDecision` | `GET /v1/actions/{id}` | The decision as it stands; after a person approves, it is `allow` with the receipt |
| `notifyWhenDecided` | `POST /v1/actions/{id}/callback` | Give one URL to be called when a person decides, so a workflow can wait rather than poll |
| `recordOutcome` | `POST /v1/actions/{id}/settle` | Say what actually happened: completed, failed or cancelled |
| `verifyReceipt` | `POST /v1/verify` | For whoever receives a receipt. Needs no key; a receipt verifies once |

Each call carries an agent key (`ask_...`), from **Agents**, **Add an agent**, then **Collect the agent's key** on its setup page, as `Authorization: Bearer` or as the `x-api-key` header. The key belongs to one agent, so every decision is recorded against the agent that asked. It can ask, check and settle; it can never approve.

## The files

| File | Format | For |
|---|---|---|
| `https://immiscible.fly.dev/openapi.json` | OpenAPI 3.1 | ChatGPT custom GPT actions, and anything that reads 3.1 |
| `https://immiscible.fly.dev/downloads/immiscible-openapi-3.0.json` | OpenAPI 3.0.3 | Importers that read 3.0 but not 3.1, such as Salesforce External Services |
| `https://immiscible.fly.dev/downloads/immiscible-power-platform.swagger.json` | Swagger 2.0 | A Power Platform custom connector: [Copilot Studio](https://immiscible.fly.dev/docs/guides/copilot-studio.md), Power Automate |
| `https://immiscible.fly.dev/downloads/n8n-ask-immiscible.json` | n8n workflow | [n8n](https://immiscible.fly.dev/docs/guides/n8n.md) |

All three descriptions come from one source, so they never disagree. They describe what a key or token can reach: every operation names its client errors (`4XX`, in the [shared error shape](https://immiscible.fly.dev/docs/api/errors.md)), and every response the `immiscible-version` header. The routes the console itself uses, which need a signed-in person's session, are only in `https://immiscible.fly.dev/openapi.json?include=internal`, marked `x-internal`.

## Which way in

| Builder | Mechanism | Guide |
|---|---|---|
| Microsoft Copilot Studio | Connect by MCP (OAuth or an API key), or import our connector | [Copilot Studio](https://immiscible.fly.dev/docs/guides/copilot-studio.md) |
| ChatGPT | Connect by MCP in developer mode, or import our OpenAPI as a custom GPT action | [below](#chatgpt) |
| Salesforce Agentforce | Import our OpenAPI 3.0 as an External Service | [below](#salesforce-agentforce) |
| n8n | Recipe, with a workflow to import | [n8n](https://immiscible.fly.dev/docs/guides/n8n.md) |
| Zapier | Recipe: Webhooks by Zapier and a catch hook | [Zapier](https://immiscible.fly.dev/docs/guides/zapier.md) |
| Make | Recipe: the HTTP module and a custom webhook | [Make](https://immiscible.fly.dev/docs/guides/make.md) |
| Lindy, Relevance AI | Connect by MCP with an agent key | [below](#lindy-and-relevance-ai) |

Two that are not listed. **Gemini Enterprise** connects custom MCP servers by OAuth, after an administrator lifts an organisation policy; we have not tried it against this server yet, so it has no card. **Wix Symphony** documents no way for an outside service to connect today: its connectors are set up by chatting, and approval happens inside Wix. When either changes, it gets a card.

## ChatGPT

**As a connector (MCP).** Where your plan has developer mode, add a connector with the URL `https://immiscible.fly.dev/mcp`. ChatGPT registers itself, you sign in to Immiscible and choose the agent it acts as. ChatGPT asks the person to confirm tool calls that change things; Immiscible decides whether the action may happen at all. See [the MCP server](https://immiscible.fly.dev/docs/guides/mcp-proxy.md#the-mcp-server).

**As a custom GPT action.** In the GPT editor, under **Actions**, choose **Import from URL** and give `https://immiscible.fly.dev/openapi.json`. Under **Authentication**, choose **API Key**, **Bearer**, and paste the agent key. Tell the GPT, in its instructions, to call `requestDecision` before any payment, email or change, and to stop on `deny`.

## Salesforce Agentforce

External Services import OpenAPI 2.0 and a subset of 3.0, not 3.1, so use the 3.0 copy.

1. In Setup, make a **Named Credential** for `https://immiscible.fly.dev` with a custom header `x-api-key` holding the agent key (through an External Credential, so the key is not visible).
2. In **External Services**, add a service from `https://immiscible.fly.dev/downloads/immiscible-openapi-3.0.json`, using that Named Credential, and select the operations.
3. In Agent Builder, add the operations as agent actions, and tell the topic to run `requestDecision` before any consequential step.

## Lindy and Relevance AI

Both connect remote MCP servers over Streamable HTTP, which `/mcp` speaks. Add a custom MCP server with the URL `https://immiscible.fly.dev/mcp` and the agent key as a bearer token or the `x-api-key` header. In Lindy, set the server's guardrail to **Ask for approval** if you also want a person in Lindy; in Relevance AI, set the tool to **Approval required** for the same.

## Waiting for a person

When the answer is `approval_required`, someone has been asked (in the console, by email, in Slack or Teams). A builder can wait two ways:

- **Poll** `getDecision` every few seconds until `decision` changes. Fine for an agent, awkward in a workflow.
- **Be called back.** Send `notifyWhenDecided` a URL; once the person decides, or the request expires, Immiscible POSTs `{ "actionId", "decision", "status", "decidedAt" }` to it, retrying with backoff for about an hour and a half if it does not answer 2xx. The call never carries the receipt: read `getDecision` with the key for that. The URL must be https on a public address (http to loopback is allowed outside production, for trying things locally).

n8n's Wait node is made for the second; Zapier and Make do it with a second Zap or scenario started by a webhook.

> **Warning**
> A builder that calls the API is choosing to ask. Pair it with something the agent cannot route around, such as the [card rail](https://immiscible.fly.dev/docs/guides/card-rail.md) or the [MCP proxy](https://immiscible.fly.dev/docs/guides/mcp-proxy.md), for anything that moves money.
