# Get an app

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

Returns one app with its actions and triggers.

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`.

### Query

- `view` · Optional · string: `summary`: no field schemas, just what you need to choose an action. Any other value returns the full app.

## Read it

In the summary, each action lists `fields`, how many inputs it has, and `discriminators`: the fields its other fields depend on, most important first. Pass them to [Get an action’s fields](https://docs.gorunner.io/api/apps/get-app-action) to narrow it.

`actions` describe the default version; a list that is empty is `null` in the full answer and `[]` in the summary. `actionsByVersion` and `triggersByVersion` list each version’s ids, for a step pinned to an older version.

Each action’s `sideEffects` says what running it does: `pure`, `reads_external` or `writes_external`. In the summary, `needsConnection: true` marks an app that takes a connection.

It sends no `ETag`.

Every answer has an `X-GoRunner-Catalog-Source` header. `fleet`: workers are checked in and runs work. `last-known` or `compiled`: no worker is, so you can read apps and edit workflows, but nothing runs. See [Catalog status](https://docs.gorunner.io/api/apps/get-catalog-status).

## The connection it needs

The full answer has `auth` when the app takes a connection. `auth.fields` lists what to send as a connection’s `config`, by `name`; `password` fields are secrets. `auth.required` is `true` when a step can’t run without one.

An app whose `auth` has `oauth2` signs in, such as Gmail. It holds the service’s `authorizationUrl`, `tokenUrl` and `scopes`. For those, [start a sign-in](https://docs.gorunner.io/api/connections/start-connection-oauth2-draft) rather than saving a secret. `auth.type` alone doesn’t say it: Gmail’s is `custom`.

## Responses

- 200 OK

  The app, in full or as a summary.

- 403 `FORBIDDEN`

  The token may not do this.

- 404 `NOT_FOUND`

  No app with this id among those the workers run. 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"

curl "$GORUNNER/api/pieces/$APP_ID?view=summary" \
  -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 res = await fetch(
  `${GORUNNER}/api/pieces/` +
    `${APP_ID}?view=summary`,
  {
    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"]

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

Response · 200 OK, shortened

```json
{
  "data": {
    "id": "http",
    "name": "HTTP Request",
    "description": "Send HTTP requests to any URL",
    "category": "HTTP",
    "version": "1.0.0",
    "versions": [
      "1.0.0"
    ],
    "actions": [
      {
        "id": "send_request",
        "name": "Send HTTP request",
        "description": "Send HTTP request",
        "sideEffects": "writes_external",
        "fields": 34,
        "discriminators": [
          {
            "field": "body_type",
            "type": "string",
            "values": [
              "none",
              "json",
              "raw",
              "form_data",
              "form_urlencoded"
            ]
          },
          {
            "field": "auth_type",
            "type": "string",
            "values": [
              "NONE",
              "BASIC",
              "BEARER_TOKEN",
              "…"
            ]
          },
          "…"
        ]
      }
    ],
    "triggers": []
  }
}
```

**Every field**

It takes no body.

### Response · 200 OK, the whole app

- `data` · object: An app as the full catalog serves it, with every action and trigger schema inlined.
  - `id` · string: The value a step stores in `pieceId`.
  - `name` · string
  - `description` · string
  - `logoUrl` · string: Icon path. A `/icons/` prefix is what classifies the app as `core`.
  - `version` · string: The version a new step is pinned to (the default), not necessarily the newest in `versions`.
  - `versions` · array of strings: Every version the fleet can run, oldest first. An unpinned step resolves to the OLDEST.
  - `icon` · string: Icon name for apps without a logo file.
  - `category` · string
  - `nodeType` · string: What kind of node this app produces on the canvas. One of `action`, `trigger`, `branch`, `loop`.
  - `kind` · string: `core` = shipped and owned by this product; `app` = third-party connector. One of `core`, `app`.
  - `actions` · array of objects or null: Actions of the DEFAULT version only. `null` when the app has none.
    - `id` · string: The value a step stores in `actionId`.
    - `name` · string
    - `description` · string
    - `sideEffects` · string: What running this does to the world. An untagged action is treated as `writes_external` (fail-safe). Anything that can write must not be test-executed without the user’s consent. One of `pure`, `reads_external`, `writes_external`.
    - `inputSchema` · object: An operation’s full input or output schema, as served by the default catalog views.
      - `type` · string
      - `properties` · object
        - `{key}` · object: One property of a full (unprojected) schema. Recursive through `properties` and `items`. Carries presentation fields (`title`, `order`, `placeholder`, `group`) that the projected views drop. Each key’s value.
          - `type` · string: JSON type: string, number, boolean, object, array.
          - `title` · string
          - `description` · string: The field’s help as the step panel shows it.
          - `default`: Default value, of any JSON type.
          - `enum` · array of strings: Closed set of legal values.
          - `enumLabels` · object: Display labels for the enum values.
          - `{key}` · string: Each key’s value.
          - `format` · string
          - `properties` · object
          - `{key}` · object: One property of a full (unprojected) schema. Recursive through `properties` and `items`. Carries presentation fields (`title`, `order`, `placeholder`, `group`) that the projected views drop. The same fields as `data.actions.inputSchema.properties.{key}` above.
          - `items` · object: One property of a full (unprojected) schema. Recursive through `properties` and `items`. Carries presentation fields (`title`, `order`, `placeholder`, `group`) that the projected views drop. The same fields as `data.actions.inputSchema.properties.{key}` above.
          - `propertyType` · string: How the value is chosen: SHORT_TEXT, LONG_TEXT, STATIC_DROPDOWN, DROPDOWN, MULTI_SELECT, DYNAMIC, JSON, CODE, CHECKBOX, NUMBER, SECRET_TEXT and similar. DROPDOWN / MULTI_SELECT / DYNAMIC mean the legal values come from POST.../options/{propertyName} at run time, not from this schema.
          - `placeholder` · string
          - `group` · string
          - `order` · integer
          - `required` · boolean
          - `minLength` · integer
          - `maxLength` · integer
          - `min` · number
          - `max` · number
          - `pattern` · string
          - `refreshers` · array of strings: Other property names whose change invalidates this property’s resolved options.
          - `refreshOnSearch` · boolean
          - `expressionEnabled` · boolean
          - `language` · string: For CODE properties: the language of the editor, e.g. javascript.
          - `displayConditions` · array of objects: ANDed conditions deciding whether this property applies. The fields they name are this operation’s gate fields — the ones you can pass as query parameters to narrow the operation detail.
          - `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.
          - `agentNotes` · string: What an agent writing this field must know beyond `description`; the step panel does not show it. The projected views append it to `description`. Absent when there is none.
      - `required` · array of strings
    - `outputSchema` · object: An operation’s full input or output schema, as served by the default catalog views. The same fields as `data.actions.inputSchema` above.
    - `sampleData` · object: Structurally accurate example of this action’s output.
    - `errorHandling` · object: Per-action retry defaults.
      - `retryOnFailure` · boolean
      - `maxRetries` · integer
      - `continueOnFailure` · boolean
    - `timeoutSeconds` · integer: Budget this action needs when the step sets none. 0 means the engine default (30s).
  - `triggers` · array of objects or null: Triggers of the DEFAULT version only. `null` when the app has none.
    - `id` · string: The value a definition’s trigger stores in its `actionId` field.
    - `name` · string
    - `description` · string
    - `type` · string: How this trigger fires. ALWAYS LOWERCASE — unlike a step’s `type` (PIECE / BRANCH / LOOP / CODE), which is uppercase. One of `manual`, `webhook`, `cron`, `poll`, `error`, `run_finished`, `callable`.
    - `inputSchema` · object: An operation’s full input or output schema, as served by the default catalog views. The same fields as `data.actions.inputSchema` above.
    - `outputSchema` · object: An operation’s full input or output schema, as served by the default catalog views. The same fields as `data.actions.inputSchema` above.
    - `sampleData` · object: Declared example of what `{{trigger.*}}` resolves to.
    - `derivesSample` · boolean: True when the real payload shape depends on this trigger’s configuration, so `sampleData` is generic and misleading. Call POST /api/pieces/{id}/triggers/{triggerId}/sample instead.
  - `auth` · object: The credential an app needs. Present means a connection is required before the app can run.
    - `type` · string: Credential family. One of `none`, `api_key`, `bearer_token`, `basic_auth`, `oauth2`, `custom`.
    - `required` · boolean
    - `description` · string
    - `fields` · array of objects
      - `name` · string
      - `title` · string
      - `type` · string: One of `string`, `password`, `boolean`.
      - `required` · boolean
      - `description` · string
      - `standalone` · boolean: On an app that also signs in with OAuth2: the credential a person makes in the service (a personal access token, an API key, a bot or app token) that works on its own and lasts. A form that cannot offer the OAuth sign-in asks for it alone. Absent means false.
    - `oauth2` · object: The OAuth2 endpoints an app declares. These are the trusted endpoints; a managed instance app is keyed off `authorizationUrl`.
      - `authorizationUrl` · string
      - `tokenUrl` · string
      - `scopes` · array of strings
      - `scopeSep` · string: Delimiter used to join scopes. Defaults to a single space; a few providers want a comma.
      - `authParams` · object: Extra query parameters merged into the authorize URL.
        - `{key}` · string: Each key’s value.
    - `connectionPiece` · string: The app whose connections this one uses (a poll trigger and its action sibling: `gmailtrigger` → `gmail`). A connection created for this app is created under that one, and serves both.
    - `helpUrl` · URL: Where to make the credential at the service.
  - `keywords` · array of strings: Words people search for the app by that its name and description do not say ("email" for Gmail). Absent for most apps.
  - `actionsByVersion` · object: Action ids each version declares, keyed by version. Validate a step pinned to an older `pieceVersion` against ITS entry, not against `actions`.
    - `{key}` · array of strings: Each key’s value.
  - `actionsAt` · object: The FULL action definitions (input schemas included) of every version other than the default, keyed by version; `actions` is the default’s. A step pinned to an older `pieceVersion` is described by its entry here — `GET /api/pieces/{id}/actions/{actionId}?version=` answers one.
    - `{key}` · array of objects: Each key’s value.
  - `triggersByVersion` · object: Trigger ids each version declares, keyed by version.
    - `{key}` · array of strings: Each key’s value.

### Response · 200 OK, with view=summary

- `data` · object: `GET /api/pieces/{id}?view=summary` — every operation of one app with no schemas at all.
  - `id` · string
  - `name` · string
  - `description` · string
  - `category` · string
  - `version` · string
  - `versions` · array of strings
  - `needsConnection` · boolean: True when the app declares auth.
  - `actions` · array of objects
    - `id` · string
    - `name` · string
    - `description` · string
    - `sideEffects` · string: Actions only; always absent for triggers. One of `pure`, `reads_external`, `writes_external`.
    - `fields` · integer: How many input properties this operation declares — a one-field action versus a forty-field one, before fetching either.
    - `discriminators` · array of objects: The gate fields this operation’s inputs depend on, MOST FAR-REACHING FIRST. These are exactly the query parameters worth supplying to the operation-detail endpoint.
      - `field` · string: Property name — send it verbatim as a query parameter, e.g. `?auth_type=BASIC`.
      - `type` · string: The field’s declared type (string, boolean, number). Query values are text and are coerced to this type.
      - `values` · array of strings: The field’s enum, when it declares one — the legal values for the query parameter.
  - `triggers` · array of objects: The same fields as `data.actions` above.

Related: [Get an action’s fields](https://docs.gorunner.io/api/apps/get-app-action) · [Get a trigger’s fields](https://docs.gorunner.io/api/apps/get-app-trigger) · [List apps](https://docs.gorunner.io/api/apps/list-apps)

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