From 7955d353614ffd93699d57f9450edefa62f0e4e5 Mon Sep 17 00:00:00 2001 From: Charles Howard <96023061+charlesrhoward@users.noreply.github.com> Date: Sat, 10 Oct 2026 14:24:27 -0400 Subject: [PATCH] docs: document API key access and API-trigger automations --- .../docs/cli/automation/ci-integration.mdx | 7 +- content/docs/integrations/api-triggers.mdx | 144 ++++++++++++++++++ content/docs/integrations/meta.json | 3 +- content/docs/mcp/security.mdx | 7 + content/docs/reference/api.mdx | 33 +++- content/docs/web/settings.mdx | 40 +++++ 6 files changed, 230 insertions(+), 4 deletions(-) create mode 100644 content/docs/integrations/api-triggers.mdx diff --git a/content/docs/cli/automation/ci-integration.mdx b/content/docs/cli/automation/ci-integration.mdx index ec2f8f6..4d50f55 100644 --- a/content/docs/cli/automation/ci-integration.mdx +++ b/content/docs/cli/automation/ci-integration.mdx @@ -12,8 +12,11 @@ a workflow. ## Prereqs -1. A PAT with the `write` scope, issued at - [mogplex.com/settings/api-keys](https://mogplex.com/settings/api-keys). +1. A PAT with the `write` scope and **Full access**, issued at + [mogplex.com/settings/api-keys](https://mogplex.com/settings/api-keys). A + key set to [Automations only](/web/settings#key-access), or held to + automations by its team, cannot start runs and gets + `403 AUTOMATION_REQUIRED`. 2. Store the token in your CI's secret store. Never commit it. 3. Pick the repo ID(s) you want to operate on: ```bash diff --git a/content/docs/integrations/api-triggers.mdx b/content/docs/integrations/api-triggers.mdx new file mode 100644 index 0000000..6bcfa70 --- /dev/null +++ b/content/docs/integrations/api-triggers.mdx @@ -0,0 +1,144 @@ +--- +title: API Triggers +description: Let another system start a Mogplex automation with a Mogplex API key and typed inputs, and limit that key to triggering automations. +--- + +An API trigger lets a server you run start a published automation with a +Mogplex API key. The automation owns the instructions, the repositories it may +touch, its agents and models, and the inputs it accepts. The caller supplies +values for those inputs and nothing else. + +Use an API trigger when the caller already holds a Mogplex API key and needs a +run id, a working branch, and run logs back. Use a +[signed webhook](/integrations/webhooks) when the sender can only send a signed +HTTP POST. + +## Set up the automation + +1. Open [Automations](/web/automations) and select the workflow's start node. +2. Set the trigger event to **API (integrations)**. +3. Under **Repository scope**, select the repositories the caller may start + work in. A trigger for any other repository returns `403 FORBIDDEN`. +4. Declare the inputs under **Inputs (JSON)**. See [Inputs](#inputs). +5. Write each agent node's instructions. Use the test payload field to try + them. +6. Publish the workflow and enable it. + +The start node shows the **Trigger endpoint** to call. + +## Inputs + +**Inputs (JSON)** is an array of fields: + +```json +[ + { "key": "site_url", "type": "string", "required": true, "maxLength": 500, "pattern": "https://.+" }, + { "key": "page_count", "type": "integer" }, + { "key": "tone", "type": "string", "enum": ["plain", "playful"] }, + { "key": "brief", "type": "json", "maxBytes": 16384 } +] +``` + +| Property | Applies to | Meaning | +| --- | --- | --- | +| `key` | All | Up to 64 lowercase letters, digits, and underscores, starting with a letter. | +| `type` | All | `string`, `integer`, `boolean`, or `json`. | +| `required` | All | The caller must send this field. | +| `description` | All | A note for whoever edits or calls the automation. | +| `maxLength` | `string` | Longest accepted value. Default 2,000 characters. | +| `pattern` | `string` | Regular expression the whole value must match. | +| `enum` | `string` | The value must be one of these. | +| `maxBytes` | `json` | Largest serialized value. Default 64 KB. | + +An automation can declare up to 32 fields, and a request's inputs can total +at most 512 KB. A request with a key that is not +declared is refused rather than ignored. + +The agent receives the inputs as JSON after the automation's instructions, +marked as untrusted data. An input cannot replace the instructions, the +repository, the branch, or the permissions. + +## Trigger a run + +```bash +curl -X POST "https://mogplex.com/api/v1/mogplex/automations/$AUTOMATION_ID/trigger" \ + -H "Authorization: Bearer $MOGPLEX_TOKEN" \ + -H "Idempotency-Key: build-4821" \ + -H "Content-Type: application/json" \ + --data '{"repoId":"'"$REPO_ID"'","input":{"site_url":"https://example.com"}}' +``` + +Get `repoId` from [`GET /repos`](/reference/api#list-repositories). The key +needs the `write` scope. + +A `202 Accepted` response returns the run: + +```json +{ + "data": { + "run": { + "automationId": "…", + "versionId": "…", + "versionNumber": 3, + "jobRunId": "…", + "workingBranch": "mogplex/automation-0123456789abcdef", + "outcome": "queued", + "replayed": false, + "started": true, + "status": "running" + } + } +} +``` + +The agent commits and pushes to `workingBranch`. It never pushes to the +default branch, merges, or enables auto-merge, and it opens a pull request only +when the automation's instructions ask for one. + +### Refusals + +Each refusal is returned before anything is queued, so no run, sandbox, or +branch is created. + +| Status | Code | Meaning | +| --- | --- | --- | +| `400` | `BAD_REQUEST` | The input failed validation. The message names each problem, including undeclared keys. | +| `403` | `FORBIDDEN` | The repository is outside the automation's repository scope. | +| `403` | `AUTOMATION_REQUIRED` | The key is held to automations, by its own access or its team's, and this automation has no API trigger. | +| `404` | `NOT_FOUND` | The automation or repository does not exist or is not owned by this account. | +| `409` | `CONFLICT` | The automation is unpublished or disabled. | +| `409` | `IDEMPOTENCY_CONFLICT` | The `Idempotency-Key` was already used with different input. | + +### Retries + +Idempotency keys are scoped to the account and the automation. Sending the +same key with the same input returns the original run with `replayed: true` +and starts nothing. Each key maps to one working branch, so a retried unit of +work returns to the same branch. Use a new key for new work. + +## Follow a run + +```txt +GET /api/v1/mogplex/automations/{automationId}/runs/{jobRunId} +POST /api/v1/mogplex/automations/{automationId}/runs/{jobRunId}/cancel +``` + +The run detail includes `status`, node runs, AI calls, and `metadata`. The +metadata records the automation version (`flow_version_id`, +`flow_version_number`), the accepted `input` and its `input_hash`, +`working_branch`, and `trigger` (credential kind, key id, and key name). + +In the app, the same runs appear on the automation's **Runs** tab with the +version, trigger, input, branch, and links to the transcript and sandbox. + +## Limit the key to automations + +A key that only needs to trigger automations should not be able to do anything +else. Set its access to **Automations only** in +[Settings → Mogplex Keys](/web/settings#mogplex-keys). The key can still read, +and it can start work only by triggering an automation with an API trigger. +See [Key access](/web/settings#key-access) for the full list of what it is +refused. + +A team owner can hold every member's key to the same rule on the team's +repositories. See [Team key access](/web/settings#team-key-access). diff --git a/content/docs/integrations/meta.json b/content/docs/integrations/meta.json index e0fb2cc..d32a8aa 100644 --- a/content/docs/integrations/meta.json +++ b/content/docs/integrations/meta.json @@ -22,6 +22,7 @@ "claude-code-and-codex", "vercel", "---Triggers---", - "webhooks" + "webhooks", + "api-triggers" ] } diff --git a/content/docs/mcp/security.mdx b/content/docs/mcp/security.mdx index a4d24bc..feadd14 100644 --- a/content/docs/mcp/security.mdx +++ b/content/docs/mcp/security.mdx @@ -52,6 +52,13 @@ PAT in the `Authorization: Bearer mog_...` header and protect it like a password | `read` | List and detail operations for repos, agents, models, automations, runs, sandboxes, logs, and env var keys on the linked Vercel project (keys and targets only — never values). | | `write` | Sandbox creation; env var creation, update, and deletion on the linked Vercel project; and automation creation, update, publication, model changes, triggers, and run cancellation. | +A PAT's owner can limit it to **Automations only** in +[Settings → Mogplex Keys](/web/settings#key-access). MCP tools call the API +with the PAT, so such a key can read, cancel runs, and trigger automations that +have an [API trigger](/integrations/api-triggers). Tools that start runs or +sandboxes, or change automations, environment variables, or settings, return +`AUTOMATION_REQUIRED`. OAuth logins are not affected. + Never place a PAT in a prompt, issue, chat transcript, repository, or checked-in client configuration. Prefer browser OAuth whenever the client diff --git a/content/docs/reference/api.mdx b/content/docs/reference/api.mdx index 40e8a81..a79b939 100644 --- a/content/docs/reference/api.mdx +++ b/content/docs/reference/api.mdx @@ -80,6 +80,26 @@ installing the [Mogplex MCP server](/mcp/install) in a supported local client. A valid token without the required scope returns `403 FORBIDDEN`. +### Key access + +Each PAT also has an access level, set by its owner in +[Settings → Mogplex Keys](/web/settings#key-access): + +| Access | Effect | +| --- | --- | +| Full access | The scopes above apply unchanged. This is the default. | +| Automations only | `read` endpoints work. Of the `write` endpoints, only triggering an automation with an [API trigger](/integrations/api-triggers) is allowed. | + +A team owner can also hold every member's PAT to automations on the team's +repositories ([Team key access](/web/settings#team-key-access)). + +A PAT held to automations gets `403 AUTOMATION_REQUIRED` from `POST /runs`, +`POST /sandboxes`, `POST /pr-reviews/rerun`, and the automation create, +update, publish, model, and delete endpoints, before anything is created. +Cancelling a run is still allowed. Triggering an automation whose +start node is not an API trigger returns the same error. OAuth access tokens +are not affected. + ### Rate limits PAT requests are limited to 60 requests per 60 seconds. Run starts also use @@ -583,6 +603,12 @@ type TriggerAutomationRequest = { }; ``` +For an automation with an [API trigger](/integrations/api-triggers), `input` +must match the start node's declared fields. Undeclared keys and invalid values +return `400 BAD_REQUEST`, and a repository outside the start node's repository +scope returns `403 FORBIDDEN`. Reusing an `Idempotency-Key` with the same input +returns the original run with `replayed: true`. + Example payload: ```json @@ -601,9 +627,13 @@ the same GitHub installation. The response is `202 Accepted`: type TriggerAutomationData = { run: { automationId: string; + versionId: string; + versionNumber: number; jobRunId: string | null; + workingBranch: string | null; // Set for API-trigger automations. outcome: string; reason: string | null; + replayed: boolean; started: boolean; status: string; runtime: { @@ -1055,7 +1085,8 @@ Send `Accept: application/json, text/event-stream`. The endpoint also accepts | --- | --- | --- | --- | | `BAD_REQUEST` | 400 | JSON, query, graph, branch, or field validation failed. | Correct the request before retrying. | | `UNAUTHORIZED` | 401 | Bearer token is missing, invalid, expired, revoked, or has the wrong OAuth audience. | Authenticate again or replace the token. | -| `FORBIDDEN` | 403 | The token lacks the required scope. | Issue a token with the required scope. | +| `FORBIDDEN` | 403 | The token lacks the required scope, or the repository is outside the automation's repository scope. | Issue a token with the required scope, or use an allowed repository. | +| `AUTOMATION_REQUIRED` | 403 | The PAT is held to automations, by its own access or its team's. | Trigger an automation with an API trigger, or ask the key's owner or team owner for full access. | | `NOT_FOUND` | 404 | The user does not own the requested resource, or it does not exist. | Verify the id using a list endpoint. | | `CONFLICT` | 409 | Current resource state prevents the operation. | Read the resource, then decide whether the operation still applies. | | `IDEMPOTENCY_CONFLICT` | 409 | The key was already used for a different request. | Use the original body or a new key. | diff --git a/content/docs/web/settings.mdx b/content/docs/web/settings.mdx index 8ba7182..ca911be 100644 --- a/content/docs/web/settings.mdx +++ b/content/docs/web/settings.mdx @@ -279,6 +279,20 @@ Open **Settings → Provider Keys** to add or remove your own model-provider cre This page supports AI Gateway, Anthropic, OpenAI, and OpenRouter. Personal keys belong to your account. Team keys use the selected team's permissions. +### Team key access + +Team Settings → **Provider Keys** also has a **Mogplex API keys** setting for +the team's repositories: + +- **Each key's own access**: a member's key can do what its owner allows. This + is the default. +- **Automations only**: every member's key is held to the + [automations-only rule](#key-access) on the team's repositories, whatever + the key itself allows. + +Only a team owner can change it. Admins and other members see it read-only. +Every change is written to the team audit log. + ## Mogplex Keys @@ -293,8 +307,34 @@ The page supports: - one-time token display at creation - copy-on-create flow - last-used metadata +- an access level for each key - revocation +### Key access + +Every key has one of two access levels. You choose it when you create the key, +it is shown on the key, and **Limit to automations** or **Allow full access** +changes it later. A change applies to the key's next request. + +| Access | What the key can do | +| --- | --- | +| **Full access** | Everything its scopes allow. This is the default, and every key created before access levels existed has it. | +| **Automations only** | Read, and start work only by triggering an automation with an [API trigger](/integrations/api-triggers). | + +An automations-only key gets `403 AUTOMATION_REQUIRED` before anything is +created when it tries to start runs or sandboxes, rerun a PR review, create, +edit, publish, or delete automations, change a model override or repository +environment variables, use hosted CLI inference, or change settings and saved +MCP servers. +MCP tools follow the same rules because they call the API with the key. + +Use **Automations only** for a key held by another system, such as a build +service that should start one named automation and nothing else. Keep **Full +access** for CI jobs and scripts that start runs directly. + +Signing in to Mogplex, and the CLI and MCP clients signed in with OAuth, do not +use these keys and are not affected. + Hosted model and sandbox access comes from the account plan, not from user-supplied provider or sandbox credentials.