# Convert a Code step to 2.0.0

**POST** `/api/code-steps/upgrade`

Converts one Code 1.0.0 step’s code and Inputs for Code 2.0.0, and answers the result. It reads and writes nothing.

Needs [an API token](https://docs.gorunner.io/api/authentication#scopes) with the **Read** permission for workflows (`workflow:read`).

## Parameters

### Body

- `code` · Required · string: The step’s `config.code`, as stored. Up to 256 KB.
- `inputs` · Optional · object or string or null: The step’s `config.inputs`: an object, a string holding a JSON object, or `null`. One expression is refused: switch Inputs to rows first.

## Apply the answer

Nothing is saved. Set the step’s `pieceVersion` to `2.0.0`, and its `config.code` and `config.inputs` to the answer’s, with [Update a workflow’s draft](https://docs.gorunner.io/api/workflows/update-workflow). Then test the step.

A note with `level` `review` means the converter left that line for you to rewrite. A step’s output stays `{result, logs}`, so later steps need no change.

## Responses

- 200 OK

  The converted step. `unchanged: true`: nothing to convert, so upgrading only changes the pin.

- 400 `VALIDATION_ERROR`

  Unreadable JSON, no `code`, or Inputs that can’t be converted. `details.field` names which.

- 403 `FORBIDDEN`

  The token lacks the **Read** permission for workflows.

- 413 `PAYLOAD_TOO_LARGE`

  The body is over 600 KB, or `code` is over 256 KB (`details.field`: `code`).

Any call can also answer: [`401 UNAUTHORIZED`](https://docs.gorunner.io/errors#UNAUTHORIZED) · [`401 TOKEN_ENDED`](https://docs.gorunner.io/errors#TOKEN_ENDED) · [`403 TOKEN_SURFACE_OFF`](https://docs.gorunner.io/errors#TOKEN_SURFACE_OFF) · [`403 FEATURE_OFF`](https://docs.gorunner.io/errors#FEATURE_OFF) · [`403 EMBED_NOT_ALLOWED`](https://docs.gorunner.io/errors#EMBED_NOT_ALLOWED) · [`403 EMBED_NOT_AVAILABLE`](https://docs.gorunner.io/errors#EMBED_NOT_AVAILABLE) · [`403 ACCOUNT_SUSPENDED`](https://docs.gorunner.io/errors#ACCOUNT_SUSPENDED) · [`415 INVALID_CONTENT_TYPE`](https://docs.gorunner.io/errors#INVALID_CONTENT_TYPE) · [`429 RATE_LIMITED`](https://docs.gorunner.io/errors#RATE_LIMITED) · [`503 BUSY`](https://docs.gorunner.io/errors#BUSY) · [`503 PAUSED`](https://docs.gorunner.io/errors#PAUSED) · [`503 SERVICE_UNAVAILABLE`](https://docs.gorunner.io/errors#SERVICE_UNAVAILABLE). See [Errors](https://docs.gorunner.io/api/errors#by-status).

Request

**curl**

```bash
GORUNNER="https://api.gorunner.io"
GORUNNER_TOKEN="grt_…"  # needs Read for workflows

curl -X POST "$GORUNNER/api/code-steps/upgrade" \
  -H "Authorization: Bearer $GORUNNER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "code": "const email = \"{{trigger.body.email}}\";\nreturn { domain: email.split(\"@\")[1] };",
    "inputs": {}
  }'
```

**JavaScript**

```js
const GORUNNER = "https://api.gorunner.io";
const TOKEN = process.env.GORUNNER_TOKEN;

const res = await fetch(
  `${GORUNNER}/api/code-steps/upgrade`,
  {
    method: "POST",
    headers: {
        Authorization: `Bearer ${TOKEN}`,
        "Content-Type": "application/json",
      },
    body: JSON.stringify({
        code: "const email = \"{{trigger.body.email}}\";\nreturn { domain: email.split(\"@\")[1] };",
        inputs: {},
      }),
  },
);
const { data } = await res.json();
```

**Python**

```python
import os, requests

GORUNNER = "https://api.gorunner.io"
TOKEN = os.environ["GORUNNER_TOKEN"]

res = requests.post(
    f"{GORUNNER}/api/code-steps/upgrade",
    headers={"Authorization": f"Bearer {TOKEN}"},
    json={
      "code": "const email = \"{{trigger.body.email}}\";\nreturn { domain: email.split(\"@\")[1] };",
      "inputs": {},
    },
)
data = res.json()["data"]
```

Response · 200 OK, shortened

```json
{
  "data": {
    "code": "const email = inputs.email;\nreturn { domain: email.split(\"@\")[1] };",
    "inputs": {
      "email": "{{trigger.body.email}}"
    },
    "pieceVersion": "2.0.0",
    "unchanged": false,
    "changes": [
      {
        "line": 1,
        "before": "\"{{trigger.body.email}}\"",
        "after": "inputs.email",
        "input": "email"
      }
    ],
    "moreChanges": 0,
    "notes": [
      {
        "level": "info",
        "text": "Test the step: its result should match its last run."
      }
    ],
    "moreNotes": 0
  }
}
```

**Every field**

### Body

- `code` · Required · string: The step’s `config.code`, as stored. Required; an empty string is accepted and answers `unchanged: true`.
- `inputs` · Optional · object or string or null: The step’s `config.inputs`: an object (the usual shape), a string holding a JSON object, or null.

### Response · 200 OK

- `data` · object: A Code step converted for Code 2.0.0 by `POST /api/code-steps/upgrade`.
  - `code` · string: The new `config.code`.
  - `inputs` · object: The new `config.inputs`: the step’s own rows in their order, then one row per new input, whose value is the original `{{ }}` text.
  - `pieceVersion` · string: The version to pin the step to.
  - `unchanged` · boolean: True when the code needed no rewrite and holds nothing to review (no `review` note): upgrading only changes the pin.
  - `changes` · array of objects: The rewrites, in code order, at most 500.
    - `line` · integer: 1-based line of the code.
    - `before` · string: The text replaced (cut at 400 characters).
    - `after` · string: What replaced it (cut at 400 characters).
    - `input` · string: The Inputs row it reads, when it reads one (several, comma-separated, for a string that held more than one `{{ }}`).
  - `moreChanges` · integer: How many rewrites were made beyond the 500 listed.
  - `notes` · array of objects: What the author should know. `review` means look at that line yourself: the converter left something it could not convert safely. At most 500 notes about the code are listed (`moreNotes` counts the rest); after them always come the runtime differences no rewrite can see (NaN, BigInt, Map/Set, UTC, console, logs on failure) and "Test the step".
    - `line` · integer: 1-based line, when the note is about one.
    - `level` · string: One of `info`, `review`.
    - `text` · string
  - `moreNotes` · integer: How many notes about the code there were beyond the 500 listed.

Related: [Code](https://docs.gorunner.io/apps/code) · [Update a workflow’s draft](https://docs.gorunner.io/api/workflows/update-workflow) · [Build tools](https://docs.gorunner.io/mcp/build-tools)

Source: https://docs.gorunner.io/api/workflows/upgrade-code-step
