GoRunner docs
Search or askSearch⌘K

Import a workflow

POST/api/workflows/import

Makes a draft workflow from an export: GoRunner’s, or another automation tool’s.

Needs an API token with the Write permission for workflows (workflow:write).

Parameters

Headers

Idempotency-KeyOptional · string

Up to 255 characters. The same request with the same key within 24 hours answers the first result again instead of importing a second copy. See Idempotency.

Body

The exported file, as it is: GoRunner’s envelope, the whole answer of Export a workflow, or just its workflow object; or a workflow exported from another automation tool. Up to 5 MiB.

gorunnerExportOptional · string

In GoRunner’s envelope: always workflow.

versionOptional · integer

In GoRunner’s envelope: always 1.

workflowOptional · object

In GoRunner’s envelope: the name, description, tags and definition. Empty name: “Imported Workflow”. A name over 255 characters is shortened, and tags past the limits are cut, rather than refused.

What carries over

The import is a new draft with a new ID. It gets none of the original’s traffic: it has no webhook address until you first update it or publish it.

Every app and action must exist here. In a GoRunner export, a step without a pieceVersion is pinned to the app’s oldest version, the one it always ran; write the version on a definition of your own (a new Code step: 2.0.0). An unfinished draft imports fine.

A field that held a secret arrives empty: the export has only [hidden secret: kept as set].

Connection IDs come over as they are. They don’t exist on another installation, so point each step at a connection there.

To see first what another tool’s export becomes, preview the import.

The report

Each node that runs in the original file is listed once in importReport.nodes, with its outcome:

mapped: an app here does the job. substituted: a general app does the same work, such as HTTP Request. parked: nothing here does it, so the step is a No Op holding the original settings, to replace.

ready says whether the step runs as imported. leftovers counts settings that had nowhere to go. needsAttention counts steps that can’t run yet.

The steps, their order and names, branches and their conditions, loops, an HTTP call’s method and address, a schedule and a code step’s code carry over. A trigger that can’t be read exactly becomes manual. Notes on the canvas are counted in warnings.

Responses

  • 201Created

    The new draft, with its definitionRev. From another tool’s export, it also has importReport.

  • The body isn’t JSON, the tree has a key it doesn’t take (the message names it), a step’s name or display name is over 255 characters, or a condition has an operator that doesn’t exist (the message lists the ones that do).

  • The token lacks the Write permission for workflows.

  • A request with this Idempotency-Key is still in progress, or its answer was too large to keep. Try again shortly.

  • The file isn’t an export GoRunner reads (the message says what it found), it holds no definition, or schemaVersion is something other than 2, 0 or absent.

  • A step names an app or action this installation doesn’t have. The message names it.

  • This Idempotency-Key was already used with a different request.

  • A GoRunner export has a step on an app this workspace may not use. Another tool’s export never answers this: such steps are parked.

  • Nothing was imported. Try again.

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

Any call can also answer: 401 UNAUTHORIZED · 401 TOKEN_ENDED · 403 TOKEN_SURFACE_OFF · 403 FEATURE_OFF · 403 EMBED_NOT_ALLOWED · 403 EMBED_NOT_AVAILABLE · 403 ACCOUNT_SUSPENDED · 413 PAYLOAD_TOO_LARGE · 415 INVALID_CONTENT_TYPE · 429 RATE_LIMITED · 503 BUSY · 503 PAUSED · 503 SERVICE_UNAVAILABLE. See Errors.

Request

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

curl -X POST "$GORUNNER/api/workflows/import" \
  -H "Authorization: Bearer $GORUNNER_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "gorunnerExport": "workflow",
    "version": 1,
    "workflow": {
      "name": "Order intake",
      "tags": [
        "orders"
      ],
      "definition": {
        "schemaVersion": 2,
        "trigger": {
          "name": "trigger",
          "type": "webhook",
          "pieceId": "webhook",
          "actionId": "catch_webhook",
          "config": {
            "methods": [
              "POST"
            ]
          },
          "valid": true
        },
        "settings": {}
      }
    }
  }'

Response · 201 Created, shortened, from another tool’s export

json
{
  "data": {
    "id": "6e9a1c3f-8b2d-4a57-9e0c-3f7b5d1a8c42",
    "name": "Order intake",
    "status": "draft",
    "definitionRev": 1,
    "triggerType": "webhook",
    "importReport": {
      "format": "external",
      "name": "Order intake",
      "nodes": [
        {
          "sourceName": "HTTP Request",
          "sourceType": "httpRequest",
          "outcome": "mapped",
          "pieceId": "http",
          "stepName": "http_request",
          "ready": true,
          "leftovers": 1
        }
      ],
      "mappedCount": 2,
      "substitutedCount": 0,
      "parkedCount": 0,
      "needsAttention": 0,
      "stepsWithLeftovers": 1
    }
  }
}
Every field

The body takes one of 2 forms.

Body, an export file, as Export a workflow gives it

gorunnerExportRequired · string

Format marker; the value is the literal string workflow, not a boolean.

One of workflow.

versionRequired · integer

Export FORMAT version — 1. Unrelated to definition.schemaVersion, which is 2.

One of 1.

exportedAtOptional · time

When the export was produced. Informational; import ignores it.

workflowRequired · object

The portable payload inside an export envelope. Import also accepts this object on its own, without the envelope around it.

nameOptional · string

On import, an empty or absent name becomes "Imported Workflow".

descriptionOptional · string
triggerTypeOptional · string

Overridden by whatever definition.trigger says, so it is effectively informational.

One of manual, cron, webhook, callable, event, error, run_finished, poll.

tagsOptional · array of strings

Trimmed and deduplicated case-insensitively on import.

definitionRequired · object

The workflow definition, and the single most important shape in this API.

A workflow definition: its fields are in Workflow definition.

Body, the workflow alone, without the envelope

nameOptional · string

On import, an empty or absent name becomes "Imported Workflow".

descriptionOptional · string
triggerTypeOptional · string

Overridden by whatever definition.trigger says, so it is effectively informational.

One of manual, cron, webhook, callable, event, error, run_finished, poll.

tagsOptional · array of strings

Trimmed and deduplicated case-insensitively on import.

definitionRequired · object

The workflow definition, and the single most important shape in this API.

A workflow definition: its fields are in Workflow definition.

Response · 201 Created

dataobject
idUUID
namestring
descriptionstring
definitionobject

The workflow definition, and the single most important shape in this API.

A workflow definition: its fields are in Workflow definition.

statusstring

draft = never published. active = live, triggers registered and the webhook URL reachable. paused = was live, now switched off. Server-owned: it moves only through publish/unpublish, never through a create or update body.

One of draft, active, paused.

triggerTypestring

Mirrors definition.trigger.type for dispatch. Derived server-side from the definition by every update and publish, so treat it as read-only in practice. A create that sends its own value keeps it until then, unchecked.

One of manual, cron, webhook, callable, event, error, run_finished, poll.

cronExpressionstring or null

Nothing derives or reads this: the schedule runs from the trigger’s own config, and nextRunAt projects from it too. Null unless a caller wrote one with PUT /api/workflows/{id}.

webhookTokenstring or null

The secret segment of the public webhook URL. Made by the first update of a webhook workflow, or at publish; absent until then (so absent in the answers of create, duplicate and import). Returned ONLY to a caller holding workflow:run: by GET /api/workflows/{id} and in the answers of update, publish, unpublish and restore (rotate answers it to its caller). It is never present on a list row, an export or a version snapshot. It is a bearer capability against an unauthenticated endpoint — possessing it is the ability to fire this workflow in production. Rotate it with POST /api/workflows/{id}/webhook/rotate.

latestVersionIdUUID or null

The published snapshot production executes. Absent means nothing has ever been published.

definitionRevinteger

Optimistic-lock revision, bumped by every definition save. Populated by GET /api/workflows/{id}, by the update response and by the answers of create, duplicate and import; absent (0) on list rows. Send it back as expectedRev on an update to refuse a clobbering write.

hasUnpublishedChangesboolean

The draft has moved ahead of the published version. Computed on the single-workflow read and on every list row; always false for a workflow never published.

folderIdUUID or null

Absent/null = uncategorized. Changed only through PUT /api/workflows/{id}/folder.

tagsarray of strings

Changed only through PUT /api/workflows/{id}/tags or the bulk addTags operation — never through the workflow update body.

testPayloadsobject or null

The saved test-fixture library, stored outside the definition so publish and version restore never reset it.

pinnedDataobject or null

The pin library ({"pins": {"<stepName>": {"data": …, "pinnedAt": …, "configHash": …, "staleAt": …, "pieceId": …}}}). A pinned step emits its fixture instead of executing, and only on test runs. configHash, staleAt and pieceId are the server’s: a step whose config changed keeps its pin marked stale, and a stale pin is not replayed (the step runs); a step whose app was replaced loses it.

workspaceIdUUID

Stamped from the credential’s scope; never accepted from a request body.

orgIdUUID
createdByUUID or null
createdByNamestring

List rows only: the creator’s name, else their email address. Absent when the creator is unknown or not a member of the organization (staff who built it on a support visit, someone since removed), and on every row for an embedded person whose installation switched presence off (an embedded person is never told an address).

createdAttime
updatedAttime

When the workflow itself was last edited. Publishing, pausing, tagging and filing it are not edits and leave it alone.

failingboolean

List rows only: the workflow is live (status: active) and its latest FINISHED production run (one that worked or failed) failed. A later run that is waiting, running, held or was cancelled changes nothing, and test runs never count. A paused or draft workflow is never failing.

failingSincetime

Only on a failing row: when the first production run failed after the last one that worked (runs cancelled, held or running in between neither break nor begin the streak). Left out for a caller without run:read.

failingRunobject

Only on a failing row: the run that decided it, its latest finished production run, with why it failed. It is lastRun unless a later run is waiting, running, held or was cancelled. Without run:read it carries status and startedAt alone.

idUUID
statusstring

One of failed.

startedAttime
finishedAttime or null
errorobject

Why it failed, as lastRun.error says it.

stepstring or null
stepKeystring or null
messagestring
summaryobject

List rows only: what a list draws instead of the definition.

triggerobject or null

The chosen trigger; null while none is chosen.

pieceIdstring
actionIdstring
displayNamestring
piecesarray of objects

The apps the workflow uses, each once, in walk order (the trigger first), with their display names.

idstring
namestring
stepCountinteger

Steps after the trigger, across branch arms, loop bodies and error paths.

needsSetupinteger

Steps (and a chosen trigger) the editor marks to configure: valid: false, or no app and action chosen.

runs7darray of integers

List rows without view=summary only: counted runs per UTC day over the last seven days, oldest first (production runs that are not a sub-flow’s, cancelled runs left out).

nextRunAttime

Next fire time of an active schedule workflow, projected from its cron in the trigger’s own timezone. Populated by the list endpoint.

lastRunobject or null

The most recent PRODUCTION run’s outcome (test runs never count). Populated on list rows only. Without run:read it carries status and startedAt alone.

idUUID
finishedAttime or null
errorobject

Only when status is failed: why.

stepstring or null

The display name of the step it failed at; null when the reason names no step.

stepKeystring or null
messagestring

The reason’s first clause, at most 160 characters.

statusstring

One of pending, running, completed, failed, cancelled, paused.

startedAttime
importReportobject

What a translation from another product could and could not carry. Every node of the source file that asks to RUN appears in nodes exactly once; canvas comments (sticky notes and other notes) are counted in warnings instead, since they are not steps. One bound, reported when it is reached: branches and loops nested deeper than this product’s own structural limit are not followed, because the alternative is letting a file decide how deep the server recurses. Real flows nest a handful of levels.

formatstring

Detected from the file: always external (another automation tool’s export).

One of external.

namestring

The name the source file gave the workflow.

nodesarray of objects
sourceNamestring

What the source file called it, so a person can find it there.

sourceTypestring

The source node’s own short type, without the source tool’s package prefix, e.g. slack or httpRequest.

outcomestring

mapped — an app here does that job. substituted — no app for it, but a generic one does the same work. parked — nothing here does it, so the step is an invalid No Op carrying the original settings.

One of mapped, substituted, parked.

pieceIdstring

The GoRunner app it became. no-op on a parked step.

stepNamestring

Its name here — what an expression referencing it says.

readyboolean

Whether the step runs as imported. False asks for a visit: a connector can be MAPPED and still need its fields, because a foreign node’s settings rarely mean the same thing here.

notestring

The honest sentence for this row.

leftoversinteger

How many of the source’s own settings are still on this node because there was no field for them. Present even when ready is true — a step can run and still be unfinished.

mappedCountinteger
substitutedCountinteger
parkedCountinteger
needsAttentioninteger

How many steps cannot run as imported — the number that decides whether this is a draft to finish or a draft to publish.

stepsWithLeftoversinteger

How many nodes still hold settings the translation could not place, whether or not they can run. NOT the same question as needsAttention: a step can run exactly as imported and still be carrying settings the original had, so a flow can be fully valid and still have translation left in it.

warningsarray of strings

File-level things the reader should know: a shape that had to be flattened (the source ran a fan-out in parallel, this product runs one chain), nodes nothing reached, comments left behind, expressions that need rewriting.