# Get an action’s fields

**GET** `/api/pieces/{id}/actions/{actionId}`

Returns one action’s fields, narrowed to the ones that apply for the values you pass.

Needs any [API token](https://docs.gorunner.io/api/authentication#scopes). No permission is checked.

## Parameters

### Path

- `id` · Required · string: The app’s id, as a step’s `pieceId` holds it: `http`, `webhook`, `schedule`.
- `actionId` · Required · string: The action’s id, as a step’s `actionId` holds it. A wrong one answers 404 naming the app’s actions.

### Query

- `view` · Optional · string: Reserved. It narrows nothing.
- `version` · Optional · string: The app version whose schema to answer, such as `1.0.0`: a Code step on `1.0.0` is described differently from one on `2.0.0`. Left out, the version a new step gets. A version not running answers 404.
- `gateValues` · Optional · object: Not sent as such: send any field of the action by its own name, such as `auth_type=BASIC&body_type=json`. Fields those values rule out are dropped.

## Narrow it

Any field can narrow the action, not only one called `operation`. [Get an app](https://docs.gorunner.io/api/apps/get-app) with `view=summary` lists which fields matter. A field that takes a list takes values separated by commas.

A field whose deciding value you didn’t send is kept, listed in `conditionalFields`, and not marked required.

Then read, each left out when empty: `filteredBy`, the values that narrowed something; `ignored`, keys that did nothing, such as a misspelling; `unresolved`, the fields still worth sending; `dynamicFields`, whose values come from [Get a field’s options](https://docs.gorunner.io/api/apps/resolve-dynamic-options).

## Responses

- 200 OK

  The action, narrowed.

- 403 `FORBIDDEN`

  The token may not do this.

- 404 `NOT_FOUND`

  No such app, or the app has no such action: the message names the ones it has. An app this workspace may not use answers 404 too.

- 503 `PIECES_UNAVAILABLE`

  GoRunner couldn’t check which apps this workspace may use. Try again.

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) · [`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 any API token
APP_ID="http"
ACTION_ID="send_request"

URL="$GORUNNER/api/pieces/$APP_ID/actions/"
URL="${URL}$ACTION_ID?auth_type=BASIC&body_type=json"
curl "$URL" \
  -H "Authorization: Bearer $GORUNNER_TOKEN"
```

**JavaScript**

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

const res = await fetch(
  `${GORUNNER}/api/pieces/${APP_ID}/actions/` +
    `${ACTION_ID}?auth_type=BASIC&body_type=json`,
  {
    headers: { Authorization: `Bearer ${TOKEN}` },
  },
);
const { data } = await res.json();
```

**Python**

```python
import os, requests

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

res = requests.get(
    f"{GORUNNER}/api/pieces/{APP_ID}/actions/"
    f"{ACTION_ID}",
    params={
      "auth_type": "BASIC",
      "body_type": "json",
    },
    headers={"Authorization": f"Bearer {TOKEN}"},
)
data = res.json()["data"]
```

Response · 200 OK, shortened

```json
{
  "data": {
    "pieceId": "http",
    "pieceVersion": "1.0.0",
    "id": "send_request",
    "name": "Send HTTP request",
    "sideEffects": "writes_external",
    "inputSchema": {
      "type": "object",
      "required": [
        "method",
        "url",
        "auth_username",
        "auth_password"
      ],
      "properties": {
        "method": {
          "type": "string",
          "enum": [
            "GET",
            "POST",
            "PUT",
            "PATCH",
            "DELETE",
            "HEAD"
          ]
        },
        "url": {
          "type": "string"
        },
        "…": {}
      }
    },
    "filteredBy": {
      "auth_type": "BASIC",
      "body_type": "json"
    },
    "unresolved": [
      "pagination_mode"
    ],
    "conditionalFields": [
      "pagination_next_path"
    ]
  }
}
```

**Every field**

It takes no body.

### Response · 200 OK

- `data` · object: One action or trigger with its schema, narrowed to the fields that apply given the gate values supplied in the query string.
  - `pieceId` · string
  - `pieceVersion` · string: The app’s default version — what a new step referencing this operation will be pinned to.
  - `id` · string: The operation id: a step’s `actionId`, or a trigger’s `actionId`.
  - `name` · string
  - `description` · string
  - `sideEffects` · string: Actions only; always empty on the trigger endpoint. One of `pure`, `reads_external`, `writes_external`.
  - `inputSchema` · object: A schema as the projections serve it: presentation fields removed, properties possibly narrowed.
    - `type` · string
    - `properties` · object
      - `{key}` · object: One property as the projections serve it: everything that constrains a legal value, nothing about screen layout (`title`, `order`, `placeholder` and `group` are dropped — 11.8% of the payload). Recursive through `properties` and `items`. Each key’s value.
        - `type` · string
        - `description` · string: The field’s whole help for whoever writes it: the step panel’s text, then the notes for an agent (`agentNotes` in the full schema).
        - `default`: Default value, of any JSON type.
        - `enum` · array of strings: Closed set of legal values.
        - `enumLabels` · object: Display labels; omitted entirely when they are identical to the enum values.
          - `{key}` · string: Each key’s value.
        - `format` · string
        - `properties` · object
          - `{key}` · object: One property as the projections serve it: everything that constrains a legal value, nothing about screen layout (`title`, `order`, `placeholder` and `group` are dropped — 11.8% of the payload). Recursive through `properties` and `items`. The same fields as `data.inputSchema.properties.{key}` above.
        - `items` · object: One property as the projections serve it: everything that constrains a legal value, nothing about screen layout (`title`, `order`, `placeholder` and `group` are dropped — 11.8% of the payload). Recursive through `properties` and `items`. The same fields as `data.inputSchema.properties.{key}` above.
        - `propertyType` · string: How the value is chosen. DROPDOWN / MULTI_SELECT / DYNAMIC mean the options come from the app at run time — see `dynamicFields`.
        - `required` · boolean: The per-property requiredness flag. The schema-level `required` array is authoritative for the narrowed view.
        - `minLength` · integer
        - `maxLength` · integer
        - `min` · number
        - `max` · number
        - `pattern` · string
        - `refreshers` · array of strings
        - `language` · string
        - `displayConditions` · array of objects: Kept deliberately: a field marked conditional must show WHAT would decide it.
          - `field` · string: The sibling property whose value decides this one. Every gate field is itself a property of the same schema, so its declared type and enum are the legal values.
          - `operator` · string: An unrecognized operator is treated permissively (the property is kept). One of `eq`, `neq`, `in`, `notIn`, `contains_any`, `exists`, `notExists`.
          - `value`: Comparison value for eq/neq, of any scalar JSON type.
          - `values` · array: Candidate list for in / notIn / contains_any.
        - `bound` · boolean: The value, though typed as text, points into the connected account (a spreadsheet, a calendar, a folder, a label): it means nothing to another account, so a template used outside the workspace it was saved in arrives with it blank. Absent when false.
        - `noExpressions` · boolean: True when `{{ }}` is NOT replaced in this field: the value is used exactly as written (Code 2.0.0’s `code`, where values come from `inputs`, `steps` and `trigger` instead). Never write an expression into such a field.
    - `required` · array of strings: Always present (possibly empty). Excludes every field listed in `conditionalFields`.
  - `outputSchema` · object: A schema as the projections serve it: presentation fields removed, properties possibly narrowed. The same fields as `data.inputSchema` above.
  - `sampleData` · object: Declared example output (for a trigger, the declared `{{trigger.*}}` shape).
  - `filteredBy` · object: The gate values that were ACTUALLY applied — the raw query intersected with the fields this operation is really gated on. If a parameter you sent is missing here, it narrowed nothing. Absent when nothing narrowed.
    - `{key}` · string: Each key’s value.
  - `ignored` · array of strings: Query keys that gate nothing on this operation — a misspelling (`bodyType` for `body_type`), or a gate belonging to a different operation. Fix these rather than believing the filter worked. Absent when empty.
  - `unresolved` · array of strings: Gate fields the SURVIVING properties still depend on and which you did not supply. Adding these as query parameters narrows the schema further.
  - `conditionalFields` · array of strings: Fields kept ONLY because their gate was left undecided. They are deliberately excluded from `required` even when the app declares them required — supply their gate to find out whether they really apply.
  - `dynamicFields` · array of strings: Properties whose legal values are not in this schema. Fetch them from POST /api/pieces/{id}/actions/{actionId}/options/{propertyName}.

Related: [Get an app](https://docs.gorunner.io/api/apps/get-app) · [Get a field’s options](https://docs.gorunner.io/api/apps/resolve-dynamic-options) · [Workflow definition](https://docs.gorunner.io/api/workflow-definition)

Source: https://docs.gorunner.io/api/apps/get-app-action
