# Get a trigger’s sample data

**POST** `/api/pieces/{id}/triggers/{triggerId}/sample`

Returns the data a trigger will deliver for the settings you send: what `{{trigger.…}}` will hold.

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

## Parameters

### Path

- `id` · Required · string: The trigger’s app id.
- `triggerId` · Required · string: The trigger’s id: in a definition, the trigger’s `actionId`.

### Body

Optional. Put the settings under `config`: sent at the top level they are ignored, and you get the stated example with `derived: false`.

- `config` · Optional · object: The trigger’s `config`, as in the definition. Left out: the trigger’s stated example.

## Why ask

A form’s data is the fields you defined, a schedule’s is its real next time, and a callable trigger’s is its stated input. The app list’s example can’t know those.

Any trigger may be asked: one that can’t work out its data answers its stated example, with `derived: false`.

## Responses

- 200 OK

  `sampleData`, and `derived`: `true` when it comes from your settings.

- 403 `FORBIDDEN`

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

- 403 `PIECE_NOT_ALLOWED`

  This workspace may not use the app.

- 404 `NOT_FOUND`

  No worker has this app, or the app has no such trigger: the message names the ones it has.

- 500 `INTERNAL_ERROR`

  The worker failed. Try again.

- 503 `WORKER_UNAVAILABLE`

  No worker is checked in, so the app couldn’t be asked. Workflows are unaffected.

- 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) · [`413 PAYLOAD_TOO_LARGE`](https://docs.gorunner.io/errors#PAYLOAD_TOO_LARGE) · [`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
APP_ID="form"
TRIGGER_ID="form_submission"

URL="$GORUNNER/api/pieces/$APP_ID/triggers/"
URL="${URL}$TRIGGER_ID/sample"
curl -X POST "$URL" \
  -H "Authorization: Bearer $GORUNNER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "config": {
      "title": "Sign up",
      "fields": [
        {
          "name": "email",
          "label": "Email"
        }
      ]
    }
  }'
```

**JavaScript**

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

const res = await fetch(
  `${GORUNNER}/api/pieces/${APP_ID}/triggers/` +
    `${TRIGGER_ID}/sample`,
  {
    method: "POST",
    headers: {
        Authorization: `Bearer ${TOKEN}`,
        "Content-Type": "application/json",
      },
    body: JSON.stringify({
        config: {
          title: "Sign up",
          fields: [
            { name: "email", label: "Email" },
          ],
        },
      }),
  },
);
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"]
TRIGGER_ID = os.environ["TRIGGER_ID"]

res = requests.post(
    f"{GORUNNER}/api/pieces/{APP_ID}/triggers/"
    f"{TRIGGER_ID}/sample",
    headers={"Authorization": f"Bearer {TOKEN}"},
    json={
      "config": {
        "title": "Sign up",
        "fields": [
          {
            "name": "email",
            "label": "Email",
          },
        ],
      },
    },
)
data = res.json()["data"]
```

Response · 200 OK, shortened

```json
{
  "data": {
    "sampleData": {
      "body": {
        "email": ""
      },
      "method": "POST",
      "submittedAt": "2026-10-25T09:00:00Z"
    },
    "derived": true
  }
}
```

**Every field**

`{"config": {…}}`, with the trigger’s configuration under `config` exactly as it would sit in the definition’s trigger. Omit for the declared fallback.

### Body

- `config` · Optional · object: The trigger’s `config` object as it would sit in the definition. Absent or empty means 'no config yet' and the declared fallback is returned.

### Response · 200 OK

- `data` · object: What `{{trigger.*}}` will contain.
  - `sampleData` · object: The payload shape. Reference its keys from steps as `{{trigger.<key>}}` (e.g. `{{trigger.body.email}}` for a webhook).
  - `derived` · boolean: True when this reflects the configuration you sent; false when it is the trigger’s generic declaration. A generic sample that looks authoritative is how authors build against a shape that never arrives.

Related: [Get a trigger’s fields](https://docs.gorunner.io/api/apps/get-app-trigger) · [Use data from earlier steps](https://docs.gorunner.io/build/use-data-from-earlier-steps)

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