GoRunner docs
Search or askSearch⌘K

Start a connection sign-in from your own button

Since v2026.10.10

POST/api/embed/v1/accounts/{accountId}/connections/oauth2/start

Starts a customer’s sign-in to a service from your own Connect button. No GoRunner screen.

Needs a partner key: Authorization: Bearer gre_…, from Platform › Partner keys. Call it from your server only.

Embed · Self-hosted with an Embed license

Parameters

Path

accountIdRequired · string

Your ID for the customer’s account: 1 to 255 bytes of UTF-8, case-sensitive. URL-encode it: it may contain /.

Body

pieceIdOptional · string

Needed for a new connection: an app that signs in, such as gmail. A trigger app is made under its action app. Optional with connectionId.

returnUrlRequired · URL

Where the browser comes back to: https (http only for localhost), on exactly one of the installation’s allowed websites or this account’s own; a wildcard entry allows none. No user name, password or #fragment. Up to 2,048 characters.

nameOptional · string

Up to 255 characters. Left blank: “Service · account” once the account is known.

connectionIdOptional · UUID

Sign a customer’s connection in again instead. Not one you manage: replace those with Create or replace a managed connection.

workspaceIdOptional · string

The workspace, by your ID. Left out: the default workspace.

What are the rarely used parameters?
configOptional · object

Your own app instead of the installation’s: clientId, clientSecret, scope.

modeOptional · string

Always redirect.

The sign-in

authorizeUrl is the service’s own consent page, with the installation’s app unless config names yours. It works once, for 10 minutes, and only for this key, account and app.

When the service sends the browser back, the connection is made as one made in the embed (managedBy: customer), audited as your key, and your page hears connection.created. Then the browser goes to returnUrl with status=connected&connectionId=…&attemptId=…, or status=error&reason=…. Never a token in that address.

Read the outcome with Check how a connection sign-in ended. Use connectionId in a workflow step.

Retries

It takes no Idempotency-Key: a stored answer would hand back a link already used. A retry starts a new sign-in; the unused one runs out.

Responses

  • 200OK

    Started: send the customer’s browser to authorizeUrl.

  • A field isn’t valid as written. details.field names it.

  • This account may not use the app.

  • connectionId names a connection you manage.

  • No such account, workspace or connection.

  • The account is deleted. Nothing starts in it.

  • returnUrl isn’t on an allowed website (details.origin).

  • There is no app to sign in with for this service.

  • Something failed on the installation’s side. Try again.

  • Sign-ins aren’t available on this server now, or the allowed websites couldn’t be read. Nothing started.

Any call can also answer: 401 UNAUTHORIZED · 403 EMBED_NOT_LICENSED · 403 IP_NOT_ALLOWED · 413 PAYLOAD_TOO_LARGE · 415 INVALID_CONTENT_TYPE · 429 RATE_LIMITED · 503 BUSY. See Errors.

Request

GORUNNER="https://automations.example.com"
GORUNNER_EMBED_KEY="YOUR_PARTNER_KEY"  # gre_…
ACCOUNT_ID="acct-bakery"

URL="$GORUNNER/api/embed/v1/accounts/$ACCOUNT_ID/"
URL="${URL}connections/oauth2/start"
curl -X POST "$URL" \
  -H "Authorization: Bearer $GORUNNER_EMBED_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "pieceId": "gmail",
    "returnUrl": "https://app.bakery.example/integrations/done?user=ada-123"
  }'

Response · 200 OK

json
{
  "data": {
    "attemptId": "Zq3XbN0iJm7dQe8TfR2wLg",
    "authorizeUrl": "https://accounts.google.com/o/oauth2/v2/auth?…&state=…",
    "expiresAt": "2026-10-25T09:10:00Z"
  }
}
Every field

Body

pieceIdOptional · string

Required for a new connection: an app that signs in (declares OAuth2, or the generic oauth2). A trigger’s app is made under its action app (gmailtrigger → gmail). With connectionId, optional and must be that connection’s.

nameOptional · string

A new connection’s name. Blank: "{Service} · {account}" once the account is known. Not with connectionId.

connectionIdOptional · UUID

Sign this existing connection (in the caller’s workspace) in again; it keeps its name and its app. Not a partner-managed one.

returnUrlRequired · URL

Where the browser comes back to: an absolute https address (http only for localhost), no user info or #fragment, whose origin is exactly an allowed website (or, with an API token on POST /api/connections/oauth2/start, this installation’s own app address). Its own query is kept; status, connectionId/reason and attemptId are set.

modeOptional · string

One of redirect. Default redirect.

configOptional · object

Your own app instead of the installation’s: clientId, clientSecret, scope (and the generic app’s authUrl, tokenUrl), and an app’s baseUrl. Sealed into the attempt. Not with connectionId.

workspaceIdOptional · string

The workspace the connection goes in (the partner’s id; default names the default one). Omitted = the account’s default workspace; the empty value is refused.

Response · 200 OK

dataobject
attemptIdstring

Names this sign-in: read it with the same credential, and it comes back on returnUrl.

authorizeUrlURL

The provider’s consent page, complete: its state is single-use and bound to this attempt. Send the person who should sign in there, and nobody else.

expiresAttime

When the link stops working (10 minutes after the start).