# Get started

Make an API token, then create, publish and run a workflow from your terminal.

## You need

- **A GoRunner account**: *Cloud only:* Sign up at [gorunner.io](https://gorunner.io), or use a workspace where you are an admin. Only a workspace admin can make API tokens. *Self-hosted only:* Your installation’s address, and a workspace where you are an admin. Only a workspace admin can make API tokens. *Embed only:* Your provider’s product, with GoRunner inside it, as an editor. Only editors can make tokens there.
- **curl and jq**: Check them with `curl --version` and `jq --version`.

## 1. Make an API token

*Cloud and Self-hosted only:*

1. Open **Settings › Workspace › API tokens** and press **New token**.
2. Name it `Get started`.
3. Under **It may**, choose **Draft, run and publish**.
4. Press **Create token** and copy the token.

*Embed only:*

1. In GoRunner inside your provider’s product, open **API tokens** and press **New token**. When MCP is on, the page is called **MCP**.
2. Name it `Get started`. Under **It may**, choose **Draft, run and publish**.
3. Press **Create token** and copy the token.

You see the token once. It starts with `grt_`. What each choice allows: [Permissions](https://docs.gorunner.io/api/authentication#scopes). *Cloud and Self-hosted only:* See [Make an API token](https://docs.gorunner.io/build/api-tokens).

```bash
GORUNNER="https://api.gorunner.io"
GORUNNER_TOKEN="grt_…"  # the token you just copied
```

## 2. Create a workflow

A workflow’s definition is a tree. `trigger` is the root, and each step hangs off the one before it in `nextAction`.

This one starts when it gets JSON, and turns the `name` it was sent into capitals with the Text Helper app.

You should see the workflow’s ID. The workflow is a **Draft**.

```bash
ID=$(curl -s -X POST "$GORUNNER/api/workflows" \
  -H "Authorization: Bearer $GORUNNER_TOKEN" \
  -H "Content-Type: application/json" \
  -d @- <<'EOF' | jq -r .data.id
{
  "name": "Hello API",
  "definition": {
    "schemaVersion": 2,
    "trigger": {
      "name": "trigger",
      "type": "webhook",
      "pieceId": "webhook",
      "actionId": "catch_webhook",
      "config": { "methods": ["POST"] },
      "nextAction": {
        "name": "shout",
        "type": "PIECE",
        "pieceId": "text",
        "actionId": "transform",
        "config": {
          "operation": "uppercase",
          "text": "{{trigger.body.name}}"
        }
      }
    },
    "settings": {}
  }
}
EOF
)
echo "$ID"
WF="$GORUNNER/api/workflows/$ID"
```

```text
acc8ce50-355c-41f9-ba19-abf97bbdc684
```

## 3. Publish it

A production run runs the published version, so publish first. Publishing saves the definition as version 1.

You should see `"status": "active"`, which the dashboard shows as **Live**.

```bash
curl -s -X POST "$WF/publish" \
  -H "Authorization: Bearer $GORUNNER_TOKEN" \
  | jq '.data | {status, latestVersionId}'
```

```text
{
  "status": "active",
  "latestVersionId": "dab47fec-…"
}
```

## 4. Run it

The JSON you send becomes the trigger’s data, so the step reads it as `{{trigger.body.name}}`.

The answer is `202 Accepted`: the run has started, not finished. Keep its ID.

```bash
RUN=$(curl -s -X POST "$WF/run?environment=production" \
  -H "Authorization: Bearer $GORUNNER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Ada Lovelace"}' | jq -r .data.id)
echo "$RUN"
```

```text
727eb26b-41ce-45d0-be20-bdf9d5f7624c
```

## 5. Get the result

[Ask for the run](https://docs.gorunner.io/api/runs/get-run). Each step’s output is in `steps[].outputData`. If it says `pending` or `running`, ask again in a second, or [follow it as it happens](https://docs.gorunner.io/api/streaming).

You should see `"status": "completed"` (Worked in the dashboard) and `ADA LOVELACE`.

```bash
curl -s "$GORUNNER/api/runs/$RUN" \
  -H "Authorization: Bearer $GORUNNER_TOKEN" \
  | jq '.data | {status, out: .steps[0].outputData}'
```

```text
{
  "status": "completed",
  "out": {
    "result": "ADA LOVELACE"
  }
}
```

## Next

- [Run a workflow](https://docs.gorunner.io/api/runs/run-workflow): Wait for the result in the same call, and every response
- [Call a workflow’s webhook](https://docs.gorunner.io/api/webhooks): Start it from another service, with no token · 5 min
- [Workflow definition](https://docs.gorunner.io/api/workflow-definition): Branches, loops and error paths in the tree

Source: https://docs.gorunner.io/api/get-started
