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

# Four wires

> One payload on four wires. Send JSON or YAML, read the answer as json, yaml, markdown or text, on every execute route and on errors, with the same fields in each.


The One API returns one payload and lets you pick the wire it travels on. The execute routes (tools, agents, workflows and the agent call door) and the bot routes under `/v1/workflows`, `/v1/schedules` and `/v1/executions` all share one format rule, so a script, a shell pipeline and an LLM can each read the same answer in the shape that suits them.

| Wire | Content type | You get |
|---|---|---|
| `json` | `application/json` | The envelope. The default. |
| `yaml` | `text/yaml` | The same envelope. Markdown fields travel as block scalars. |
| `markdown` | `text/markdown` | The result rendered by the same renderer the [MCP server](/developer-tools/mcp/quickstart) uses, with the execution id in a footer. |
| `text` | `text/plain` | The bare result content, nothing else. |

## Choose the wire

The first rule that applies wins:

1. `format` in the body, or `?format=` in the query.
2. The `Accept` header. The highest `q` value that names a known type wins; ties go to the first listed. `*/*` and unknown types are skipped, and an `Accept` is a preference, never a `400`.
3. The request's `Content-Type`: `text/yaml`, `application/yaml` or `application/x-yaml` answers in YAML, anything else in JSON.

| `Accept` | Wire |
|---|---|
| `application/json` | `json` |
| `text/yaml`, `application/yaml`, `application/x-yaml` | `yaml` |
| `text/markdown` | `markdown` |
| `text/plain` | `text` |

An explicit `format` that is not one of `json`, `yaml`, `markdown` or `text` is `400 invalid_format`, answered as JSON. Streams (`stream: true`, `execute-stream`) are exempt and always send server-sent events.

## Send JSON or YAML

A request body is JSON or YAML, whichever its `Content-Type` says. Tool fields can be sent with or without the `params` wrapper.

The same call on the tools door, once with JSON and once with YAML:

```bash
curl -s -X POST https://api.plungeai.com/v1/tools/calculator-tool-agent/execute \
  -H "Authorization: Bearer $PLUNGE_API_KEY" -H 'Content-Type: application/json' \
  -d '{"params":{"expression":"7*6"}}'
```

```bash
curl -s -X POST https://api.plungeai.com/v1/tools/calculator-tool-agent/execute \
  -H "Authorization: Bearer $PLUNGE_API_KEY" -H 'Content-Type: text/yaml' \
  --data-binary $'expression: "7*6"\n'
```

On a workflow route, `format`, `input` and `inputs` sit at the top of the YAML next to `workflow:`. They mean exactly what the JSON fields mean and are removed before the engine sees the workflow:

```yaml
format: markdown
workflow:
  name: w
  tasks:
    - id: t1
      type: task
      agent: calculator-tool-agent
      expression: "7*6"
```

A bare `agent:` body works on the agent call door, `POST /v1/execute`: `agent: calculator-tool-agent`, the agent's own fields and `format: text`. See [Agent call](/api-reference/agent-call/agent-call).

## Read it on four wires

The same run, asked four ways:

<CodeGroup>

```bash json
curl -s -X POST https://api.plungeai.com/v1/tools/calculator-tool-agent/execute \
  -H "Authorization: Bearer $PLUNGE_API_KEY" -H 'Content-Type: application/json' \
  -d '{"params":{"expression":"7*6"}}'
```

```bash yaml
curl -s -X POST https://api.plungeai.com/v1/tools/calculator-tool-agent/execute \
  -H "Authorization: Bearer $PLUNGE_API_KEY" -H 'Content-Type: application/json' \
  -H 'Accept: text/yaml' -d '{"params":{"expression":"7*6"}}'
```

```bash markdown
curl -s -X POST https://api.plungeai.com/v1/tools/calculator-tool-agent/execute \
  -H "Authorization: Bearer $PLUNGE_API_KEY" -H 'Content-Type: application/json' \
  -H 'Accept: text/markdown' -d '{"params":{"expression":"7*6"}}'
```

```bash text
curl -s -X POST "https://api.plungeai.com/v1/tools/calculator-tool-agent/execute?format=text" \
  -H "Authorization: Bearer $PLUNGE_API_KEY" -H 'Content-Type: application/json' \
  -d '{"params":{"expression":"7*6"}}'
```

</CodeGroup>

The `json` answer:

```json
{"ok":true,"content":"# Calculator: 7*6\n\n## 1. Expression\n7*6\n\n## 2. Result\n42\n\n*2 results*","execution_id":"…","request_id":"…"}
```

The `yaml` answer carries the same fields:

```yaml
ok: true
content: |-
  # Calculator: 7*6

  ## 1. Expression
  7*6

  ## 2. Result
  42

  *2 results*
execution_id: …
request_id: …
```

The `markdown` answer is the content followed by a footer naming the execution, so a reader can quote the id:

```markdown
# Calculator: 7*6

## 1. Expression
7*6

## 2. Result
42

*2 results*

---
execution: `…` — use this id for plungeai_get_result / plungeai_followup on this run.
```

The `text` answer is only the content, from `# Calculator: 7*6` to `*2 results*`.

A route that answers with a pointer instead of a result (an async run) has no `content`. Its `markdown` and `text` wires then list the pointer's top-level keys (`workflow_id`, `execution_id`, `task_id`, `status`), one per line, so nothing is dropped.

## Response headers

- `x-request-id` is on every answer, on every wire.
- `X-Execution-Id` is on every answer that belongs to an execution.
- `X-Error-Code` is on every error.

## Errors on four wires

An error keeps its `code` and `message` on every wire. The extra fields travel too: `missing`, `contract`, `hint` and the execution id render on `markdown`, `missing` on `text`, and every field survives `json` and `yaml`.

A missing field, asked as text:

```bash
curl -s -X POST https://api.plungeai.com/v1/tools/calculator-tool-agent/execute \
  -H "Authorization: Bearer $PLUNGE_API_KEY" -H 'Content-Type: application/json' \
  -H 'Accept: text/plain' -d '{"params":{}}'
```

```text
invalid_params: params failed card validation
missing: expression
```

An unknown `format` is always JSON, with `X-Error-Code: invalid_format`:

```json
{"error":{"code":"invalid_format","message":"format must be one of: json, yaml, markdown, text"}}
```

## MCP and the CLI

The MCP tools answer `markdown` by default. Pass `format: "json"` for the same outcome as a JSON document in `text` plus `structuredContent`. The CLI takes `--json` on every verb for one JSON document on stdout.

## Next steps

<CardGroup cols={2}>
<Card title="Errors, limits and headers" icon="book" href="/getting-started/rate-limits">
Rate limits and the shared error shape.
</Card>
<Card title="Control a bot" icon="robot" href="/bots/rest-mcp-cli">
The bot routes on all three doors.
</Card>
</CardGroup>
