> ## Documentation Index
> Fetch the complete documentation index at: https://www.plungeai.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# plungeai-in-lovable

> Connect Lovable to PlungeAI (Ocean Studio) — a personal chat connector (any plan) so Lovable's chat can operate PlungeAI via MCP while building, and a workspace-admin app connector so shipped apps call the One API in production with attached auth, plus a plungeai_whoami + plungeai_list_agents…


Connect Lovable to PlungeAI (Ocean Studio) — a personal chat connector (any plan) so Lovable's chat can operate PlungeAI via MCP while building, and a workspace-admin app connector so shipped apps call the One API in production with attached auth, plus a plungeai_whoami + plungeai_list_agents verify. Use when the user is in Lovable and says connect / install / set up PlungeAI, mentions Connectors or Custom MCP, or a Lovable-built app can't reach PlungeAI. For another builder use its plungeai-in-<tool> skill; for an unlisted but MCP-capable client use plungeai-mcp-setup's generic client config.

[Download zip](https://skills.plungeai.com/plungeai-in-lovable.zip) · [View raw SKILL.md](https://skills.plungeai.com/plungeai-in-lovable/SKILL.md)

Two connectors, two purposes: a **chat connector** (any plan) so Lovable's
chat can operate PlungeAI while building, and an **app connector** (workspace
admin) so the apps users ship call the One API in production.

## Prerequisites

- An `ozk_` key: Dashboard → **One API → Keys** (https://dashboard.plungeai.com) —
  self-service, shown once, copy it now.

## Path A — chat connector (any plan, 2 minutes)

**Connectors → + → MCP server**: Server name `PlungeAI`, Server URL
`https://mcp.plungeai.com/v1`, Authentication → bearer token / API key →
paste the `ozk_` key. Lovable's chat now has the 20 `plungeai_*` tools while
building (tool map: **plungeai-mcp-setup**).

- Chat connectors are **personal**: others in the workspace connect the
  same server themselves, each with their own key.
- They are **build-time only** — never part of the published app. That is
  exactly why Path B exists.
- Workspace admins can switch custom MCP servers off for everyone:
  **Connectors → Admin settings → Chat connectors → "Custom MCP"**. A
  non-admin who can't find "MCP server" in the picker is hitting this
  toggle.

## Path B — app connector (workspace admin)

Creates a reusable custom connector: workspace members connect it to their
apps, each pasting their own key; Lovable then attaches auth to every One
API call the generated app makes.

### 1. Create the connector (Connectors → + → Custom connector)

| Form field | Value |
| --- | --- |
| Display name | PlungeAI |
| Category | Development |
| Documentation URL | https://api.plungeai.com/docs |

### 2. Authentication

| Field | Value |
| --- | --- |
| Authentication method | Bearer token |
| API base URL | `https://api.plungeai.com` |
| Test request → Method | GET |
| Test request → Path | /v1/agents |

Users paste their own `ozk_` key when they connect an app; Lovable verifies
it against the verification path (green check = valid key).

### 3. Agent knowledge (attach to the connector)

Paste this whole block into the connector's agent knowledge. It is the One
API as deployed (2.3.0), so the generated app can implement saved workflows,
bots, executions, schedules, triggers, memory, skills, templates and
connections, not only "run an agent". The connector's auth layer already
attaches the key: generated code never adds its own Authorization header.
The minimal saved-workflow body (`workflow:` / `tasks:` YAML) is in **plungeai-api-setup**.

```text
PlungeAI One API 2.3.0. Base URL https://api.plungeai.com. Spec: GET /v1/openapi.json (no auth) - never invent a route.
AUTH: Authorization: Bearer ozk_YOUR_KEY on every call; key in an env var, server side only. When a connector attaches auth, NEVER add your own Authorization header.
ME: GET /v1/whoami -> {user_id, via, tier, key_label}. GET /v1/key -> {data:{label, limit, usage, rate_limit}}.
FIND (never from memory): GET /v1/discovery/search?q=<capability>&kind=agents -> {cards} (without kind, skill cards come first). POST /v1/discovery/resolve {task}. GET /v1/agents. GET /v1/tools. GET /v1/tools/{id} = the contract.
DOOR 1, one agent or tool: POST /v1/agents/{id}/execute {prompt|input, sync?, model?} -> 200 {content, workflow_id, task_id, request_id}.
  POST /v1/tools/{id}/execute {operation, params} -> {ok, content, outcome}; 422 invalid_params echoes the contract.
DOOR 2, saved workflow or bot: POST /v1/workflows/{id}/execute {input?, inputs?} -> {success, workflow_id, final_task_id, request_id, content}, synchronous.
  POST /v1/workflows/{id}/execute-stream = SSE. Inline YAML: POST /v1/workflows/execute. No content? GET /v1/workflows/results/{workflowId}/{taskId} (taskId = final_task_id).
DOOR 3, Agent Call: POST /v1/execute, the body is the program: {agent:"<saved id>[@n]", input} or {workflow:{...}} or {tasks:[...]}. dry_run:true plans without running;
  on_behalf_of:"<customer id>" uses that customer's connections.
ASYNC: POST /v1/agents/{id}/execute {sync:false} -> 202 {workflow_id, task_id, request_id}; redeem GET /v1/agents/results/{workflowId}/{taskId} -> {content}; 404 not_ready = poll, 2s+.
EXECUTIONS: the run id is the body's workflow_id (also the x-execution-id header, and your x-trace-id UUID if you sent one; replaying one is 409 duplicate_execution_id).
  GET /v1/executions (source, status, workflow_id). GET /v1/executions/{id}: running | completed | incomplete | failed | cancelled | needs_input | needs_approval.
  GET /v1/executions/{id}/output -> {content, steps}. GET /v1/executions/{id}/files. GET /v1/executions/{id}/conversation. DELETE /v1/executions/{id}. GET /v1/executions/{id}/stream = SSE.
  POST /v1/executions/{id}/continue {answer | approve, allow_scope: once|run|always}. POST /v1/executions/{id}/followup {text}. POST /v1/executions/{id}/cancel.
  POST /v1/executions/{id}/steer {text} queues a message for a live run (202), else 409 execution_finished.
WORKFLOWS: GET|POST /v1/workflows. GET|PATCH|DELETE /v1/workflows/{id}. GET|POST /v1/workflows/{id}/versions. POST /v1/workflows/{id}/versions/{versionId}/restore.
  Save needs {name, kind, yaml}; kind = workflow|agent|bot|campaign. GET /v1/workflows lists every kind unless ?kind=bot (or campaign). 422 invalid_workflow lists errors, writes nothing.
SCHEDULES: POST /v1/schedules {name, schedule, workflow_id, timezone?, parameters?}; schedule = a cron, or "@once" with run_at (ISO-8601 WITH a UTC offset, in the future);
  400 run_at_required | run_at_past. GET /v1/schedules. GET|PATCH|DELETE /v1/schedules/{id}. GET /v1/schedules/{id}/runs (execution_id per run).
  POST /v1/schedules/{id}/run. POST /v1/schedules/{id}/pause. POST /v1/schedules/{id}/resume. POST /v1/schedules/{id}/wake {note?, in?} fires it once, now or later.
TRIGGERS (every call names schedule_id; a secret is shown once): GET|POST /v1/triggers/webhook. DELETE /v1/triggers/webhook/{token}. POST /v1/triggers/webhook/{token}/rotate.
  The same four under /v1/triggers/email {allowed_from}. GET|POST /v1/triggers/hooks {url, events}. DELETE /v1/triggers/hooks/{id}.
PERMISSIONS: GET|PUT /v1/workflows/{id}/permissions {classes:{send|write|pay|delete: allow|ask|deny|hand_off}, locks, budget_usd_run, budget_usd_month}; locks need a team admin (403 lock_admin_required).
BOT DATA: GET /v1/workflows/{id}/workspace-files. GET /v1/workflows/{id}/workspace-files/download?path=. GET /v1/workflows/{id}/inbox. GET|POST /v1/workflows/{id}/bindings {channel, sender_id}.
  DELETE /v1/workflows/{id}/bindings/{channel}/{sender_id}. GET /v1/channels. POST /v1/channels/pair {channel}.
  GET|POST /v1/bot-groups {name, members = 2-6 of your bot ids}. PUT|DELETE /v1/bot-groups/{id}. GET /v1/bot-groups/{id}/thread.
MEMORY: GET /v1/memory/recall?q=. POST /v1/memory/remember {text, scope: memory|user}. POST /v1/memory/forget {id | text}. GET /v1/memory/runs?q= (q required). GET /v1/memory/runs/{id}.
SKILLS: GET /v1/skills. POST /v1/skills/learn {name, body} saves the body you send (it does not distill a URL). DELETE /v1/skills/{id}.
TEMPLATES: GET /v1/templates?kind=workflow|agent|bot. GET /v1/templates/{id}. POST /v1/templates/{id}/use {name?} -> 201 {workflow}.
CONNECTIONS: GET /v1/connections. POST /v1/connections/{provider} {api_key, on_behalf_of?}. DELETE /v1/connections/{provider}. POST /v1/connections/{provider}/link -> {url, expires_at}.
MODELS (OpenAI-shaped, Bearer only): GET /v1/models. POST /v1/chat/completions. POST /v1/embeddings.
TRACES: GET /v1/traces/{id}, id = the run's workflow_id.
LISTS: {workflows|executions|schedules|cards:[...], total, limit, offset, has_more}; POST /v1/schedules -> {schedule}.
ERRORS: {"error":{"code","message"}} plus an X-Error-Code header. 400 validation; 401 unauthorized; 403 refused | agent_not_active; 404 <thing>_not_found (a stranger's id too);
  409 approval_required, or not_paused | execution_finished | duplicate_execution_id | name_taken; 422 invalid_params; 429 rate_limited + Retry-After; 502/503 retry once.
  424 connection_required | credential_required carries error.connect {provider, method, link}: connect via POST /v1/connections/{provider} or its /link.
FENCES: 403 refused is final - surface it, never retry. 409 approval_required is a human boundary - never approve for the user. tools/{id}/execute: a human approves in Studio, then re-issue.
  A paused agent reply: re-send with approved:true plus its action_token (both). A run reading needs_approval: POST /v1/executions/{id}/continue, never the original call.
```

## Verify

1. Chat: "use plungeai_whoami to confirm my identity" → an identity card.
2. App connector: connecting an app runs Lovable's verification
   (`GET /v1/agents`) → green check.
3. "use plungeai_list_agents to search 'web search'" → live results from
   the active agent catalog.

## Quirks

- Two different auth surfaces: the chat connector's key powers the
  BUILDER; each app's key is pasted by its owner when connecting the app
  connector. Never hardcode any key in the app itself.
- If generated code contains an `Authorization` header, the knowledge
  wasn't attached to the connector, or the connector step was skipped —
  re-check step 3; the connector's own auth layer is the only place
  credentials belong.
- The app connector is workspace-admin gated; non-admins use Path A for
  building and hand the admin this file for Path B.

## Where next

- Route-by-route API manual (workflows, bots, executions, schedules, triggers, connections, discovery, traces): **plungeai-api-setup**.
- Operating the `plungeai_*` tools in chat: **plungeai-mcp-setup**.
- Picking MCP vs the One API for a given job: **choose-your-plungeai-door**.
- An unlisted but MCP-capable client, or the shared connect concepts (native
  remote vs. stdio bridge, key hygiene): **plungeai-mcp-setup**.
- Full guide: https://mcp.plungeai.com/docs#3-connecting-clients
