Skip to content

Finish a connect

View as Markdown
POST
/v1/connections/finish
curl --request POST \
--url https://example.com/v1/connections/finish \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "state": "example", "code": "example", "installationId": "example", "setupAction": "example", "error": "example", "errorDescription": "example" }'

Takes what the app sent back to the callback page (state and code, with installationId and setupAction from a GitHub App; or error). Only whoever started the request may finish it. Exchanges the code, learns the account, compares what was granted with what was asked and stores the connection; a run that waits goes on. A person who declined, or who granted less than asked, gets kind: 'declined' and the request’s missing permissions. A GitHub App’s attaches an installation only if the person’s GitHub account reaches it: the one GitHub sent back, the one they picked at the start, or the only one they reach. When they reach several and picked none, it answers kind: 'pick-installation': the request stays pending with its installations to pick from (start it again with installationId, or newInstallation).

Idempotency-Key
string
>= 1 characters

Caller-supplied idempotency key, scoped to the caller: the same key from someone else in the tenant is their own request (from 0.1.5). Retries with the same key return the original response byte-identical (per docs/API-ROUTE-CONVENTIONS.md §3.1). A retry sent while the first request still runs is answered 409 idempotency-key-in-flight with Retry-After, on a runtime whose store holds keys (from 0.1.5); retry after it, and you get the first request’s answer. An answer that carries a secret (a new API key or public run token, a session token, a generated signing secret) isn’t kept: a retry gets 409 idempotency-key-replay-withheld, with the first request’s status and when it succeeded (from 0.1.5). A request whose key store can’t be read before it runs is answered 503 idempotency-store-unavailable with Retry-After: nothing ran, so retry with the same key (from 0.3.0).

Media typeapplication/json

What the app sent back to the callback page, each as a string. Only whoever started the request may finish it.

object
state
required

The one the app sent back.

string
>= 1 characters <= 2048 characters
code
string
>= 1 characters <= 2048 characters
installationId
string
>= 1 characters <= 2048 characters
setupAction
string
>= 1 characters <= 2048 characters
error
string
>= 1 characters <= 2048 characters
errorDescription
string
>= 1 characters <= 2048 characters
Examplegenerated
{
"state": "example",
"code": "example",
"installationId": "example",
"setupAction": "example",
"error": "example",
"errorDescription": "example"
}

The outcome.

Media typeapplication/json
object
kind
required

declined: the person declined, or granted less than asked (request.missing). pick-installation: a GitHub App’s person reaches several installations and picked none; the request stays pending with its installations.

string
Allowed values: connected declined pick-installation
request
required

A connect: the owner goes to connectUrl, consents at the app, and comes back. A run that needs a connection it lacks waits on one.

object
requestId
required
string format: uuid
envName
required
string
appId
required
string format: uuid
app
required

The app’s entry id.

string
owner
required

Who owns a connection: one member (kind: member, with their userId), or the company (kind: company, the tenant’s own account).

object
kind
required
string
Allowed values: member company
userId

The member. Present when kind is member.

string
permissions
required

The permissions asked for: the ones needed, and the ones already granted.

Array<string>
says
required

What each asks for, in plain words.

Array<string>
reconnects

The connection it connects again; the same account is required.

string format: uuid
runId

The run that waits for it.

string
name

The tool’s name for the connection, when a run waits.

string
startedBy

Who started it last: <kind>:<id>. Only they may finish it.

string
state
required
string
Allowed values: pending connected declined expired failed
failure

Why it failed: account-mismatch, app-refused, store-write-failed.

string
missing

The permissions the app granted less than asked.

Array<string>
installations

A GitHub App’s, while it’s pending: the app’s installations the person’s GitHub account reaches, when the finish found several and none was picked. They pick one and start again with installationId, or install the app on another account with newInstallation.

Array<object>

A GitHub App installation the person can reach.

object
installationId
required
string
account
required

The account it’s on: its login, or the enterprise’s slug.

object
id
required

The account’s stable id at the app.

string
label
required

What people see: an email address, a login.

string
connectionId

The connection it made.

string format: uuid
connectUrl
required

Where the owner starts.

string format: uri
expiresAt
required
string format: date-time
createdAt
required
string format: date-time
createdBy
required
string
connection

Present when kind is connected.

object
connectionId
required
string format: uuid
envName
required
string
appId
required

The registration it goes through.

string format: uuid
app
required

The app’s entry id.

string
owner
required

Who owns a connection: one member (kind: member, with their userId), or the company (kind: company, the tenant’s own account).

object
kind
required
string
Allowed values: member company
userId

The member. Present when kind is member.

string
account
required

Whose account a connection is at the app.

object
id
required

The account’s stable id at the app.

string
label
required

What people see: an email address, a login.

string
permissions
required

The entry’s permission keys the app granted.

Array<string>
state
required

working: runs can use it. needs-reconnecting: the app no longer accepts it; connect again. removing: a disconnect is under way. removed: gone.

string
Allowed values: working needs-reconnecting removing removed
stateReason

Why it’s in its state: invalid-grant (the app withdrew the grant), no-refresh-token (the app gave no way to renew it), token-missing (its stored token is gone), store-write-failed (its token couldn’t be stored at the connect), installation-missing (the GitHub App was uninstalled from the account), installation-permissions (an owner took permissions from the installation), suspended (the installation was suspended), sessions-revoked (Google revoked the person’s sessions), access-expired (the app gave no refresh token, and its access token ends within a minute, or has ended). Other values may be added; state says what to do.

string
installationId

A GitHub App’s installation.

string
accessEndsAt

When its access token ends, for a connection the app gave no refresh token. From one minute before then, it needs reconnecting (access-expired), and reads say so too. Absent for one that renews.

string format: date-time
connectedAt
required

When its current grant was stored: the connect, or the last reconnect.

string format: date-time
lastUsedAt

When a run last used it, to the hour.

string format: date-time
createdAt
required
string format: date-time
createdBy
required
string
updatedAt
required
string format: date-time
removedAt
string format: date-time
removedBy
string
removedReason
string
Allowed values: disconnected revoked-at-app uninstalled registration-removed replaced
withdrawn

What a removal did at the app. at-app: access was withdrawn there. app-failed: the app refused the revoke; the token is gone here all the same. kept-for-other-connection: another live connection uses the same grant. not-supported: the app has no revoke that would touch only this connection.

string
Allowed values: at-app app-failed kept-for-other-connection not-supported
reviewerSeat

On a server with approvals, for a member who connected: whether they have a reviewer seat, which approving a send from their own account needs.

boolean
Example
{
"kind": "connected",
"request": {
"owner": {
"kind": "member"
},
"state": "pending"
},
"connection": {
"owner": {
"kind": "member"
},
"state": "working",
"removedReason": "disconnected",
"withdrawn": "at-app"
}
}

Malformed body, unknown field or no state; or neither code nor error (bad-input, details.field).

Media typeapplication/json
object
error
required
object
code
required

Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).

string
message
required
string
details

Optional, kind-specific.

object
key
additional properties
any
requestId
required

Server-assigned request id; also echoed via X-Request-Id header.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {},
"requestId": "example"
}
}

Missing / malformed / expired / revoked bearer token.

Media typeapplication/json
object
error
required
object
code
required

Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).

string
message
required
string
details

Optional, kind-specific.

object
key
additional properties
any
requestId
required

Server-assigned request id; also echoed via X-Request-Id header.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {},
"requestId": "example"
}
}

Someone other than whoever started the request (connection-not-yours); or a GitHub App’s person whose GitHub account doesn’t reach the installation, or any (connection-installation-unreachable, with details.connectRequestId: start that request again with newInstallation to install the app on their account).

Media typeapplication/json
object
error
required
object
code
required

Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).

string
message
required
string
details

Optional, kind-specific.

object
key
additional properties
any
requestId
required

Server-assigned request id; also echoed via X-Request-Id header.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {},
"requestId": "example"
}
}

No request for that state (connection-request-not-found).

Media typeapplication/json
object
error
required
object
code
required

Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).

string
message
required
string
details

Optional, kind-specific.

object
key
additional properties
any
requestId
required

Server-assigned request id; also echoed via X-Request-Id header.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {},
"requestId": "example"
}
}

Idempotency-Key was reused with a different body; the request was finished already (connection-request-used); a reconnect signed in to another account (connection-account-mismatch); or the connection is still being disconnected: disconnect it again to finish, then connect (connection-removing).

Media typeapplication/json
object
error
required
object
code
required

Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).

string
message
required
string
details

Optional, kind-specific.

object
key
additional properties
any
requestId
required

Server-assigned request id; also echoed via X-Request-Id header.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {},
"requestId": "example"
}
}

The request expired (connection-request-expired), or the sign-in took longer than its state lives: start again (connection-state-expired).

Media typeapplication/json
object
error
required
object
code
required

Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).

string
message
required
string
details

Optional, kind-specific.

object
key
additional properties
any
requestId
required

Server-assigned request id; also echoed via X-Request-Id header.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {},
"requestId": "example"
}
}

The request body is over the API’s limit (request-too-large; details.maxBytes says how much).

Media typeapplication/json
object
error
required
object
code
required

Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).

string
message
required
string
details

Optional, kind-specific.

object
key
additional properties
any
requestId
required

Server-assigned request id; also echoed via X-Request-Id header.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {},
"requestId": "example"
}
}

Server error (unmapped domain code or framework crash).

Media typeapplication/json
object
error
required
object
code
required

Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).

string
message
required
string
details

Optional, kind-specific.

object
key
additional properties
any
requestId
required

Server-assigned request id; also echoed via X-Request-Id header.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {},
"requestId": "example"
}
}

The app wouldn’t give a token for the code: its client id, secret or redirect URL (connection-app-refused).

Media typeapplication/json
object
error
required
object
code
required

Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).

string
message
required
string
details

Optional, kind-specific.

object
key
additional properties
any
requestId
required

Server-assigned request id; also echoed via X-Request-Id header.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {},
"requestId": "example"
}
}

The connection couldn’t be stored just now (connection-store-failed), or the Idempotency-Key store couldn’t be read before the request ran (idempotency-store-unavailable, with Retry-After).

Media typeapplication/json
object
error
required
object
code
required

Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).

string
message
required
string
details

Optional, kind-specific.

object
key
additional properties
any
requestId
required

Server-assigned request id; also echoed via X-Request-Id header.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {},
"requestId": "example"
}
}

See also