Skip to content

Begin Continue with GitHub

GET
/auth/github/start
curl --request GET \
--url 'https://api.pealboard.com/auth/github/start?client=web&codeChallengeMethod=S256' \
--header 'Authorization: Bearer <token>'

A GET, so a native application can open it in a system browser. Everything else about signing in with GitHub is a POST from a page, which a phone cannot do and keep the browser it will come back to.

Open it on the workspace application’s own origin (https://app.pealboard.com/auth/github/start), never on the API host: the OAuth state lives in a __Host- cookie belonging to that origin, and a flow started anywhere else arrives at the callback with no cookie and fails.

With client=mobile, send codeChallenge — base64url(SHA-256(verifier)) for a verifier the app generated. When GitHub is done the browser is sent to pealboard://auth?token=<code>. That code is not a session: it is single-use, expires in 60 seconds, and is exchanged for a session token at POST /auth/github/exchange by sending the verifier. A private-use URI scheme is not claimed by an operating system, so any application on the device can receive that redirect; the verifier is what makes receiving it worthless.

Access. No credential. Open to any caller. This is where signing in begins, so there is nobody to authenticate yet. It writes one short-lived row naming a PKCE challenge and redirects to GitHub; the credential it eventually issues is bound to that challenge.

client

mobile hands the session back through pealboard://.

string
default: web
Allowed values: web mobile

mobile hands the session back through pealboard://.

codeChallenge

Required for mobile. base64url(SHA-256(verifier)) of a verifier the app generated and keeps. Without it the code this flow issues could be redeemed by whatever else on the device answered the redirect.

string

Required for mobile. base64url(SHA-256(verifier)) of a verifier the app generated and keeps. Without it the code this flow issues could be redeemed by whatever else on the device answered the redirect.

codeChallengeMethod

S256 only. plain is a challenge an interceptor can also compute.

string
default: S256
Allowed values: S256

S256 only. plain is a challenge an interceptor can also compute.

A redirect to GitHub’s authorization screen.

No valid credentials.

Media typeapplication/json
object
error
required
object
code
required

A stable identifier for the kind of failure. Safe to branch on.

string
message
required

What went wrong, written for a person.

string
detail

Structured particulars, when there are any.

object
key
additional properties
remedy

What to do about it, when there is something to do.

string
requestId
required

Quote this when asking about a specific failure.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"detail": {
"additionalProperty": "example"
},
"remedy": "example",
"requestId": "example"
}
}

Authenticated, but not permitted.

Media typeapplication/json
object
error
required
object
code
required

A stable identifier for the kind of failure. Safe to branch on.

string
message
required

What went wrong, written for a person.

string
detail

Structured particulars, when there are any.

object
key
additional properties
remedy

What to do about it, when there is something to do.

string
requestId
required

Quote this when asking about a specific failure.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"detail": {
"additionalProperty": "example"
},
"remedy": "example",
"requestId": "example"
}
}

No such resource, or it is not visible to you.

Media typeapplication/json
object
error
required
object
code
required

A stable identifier for the kind of failure. Safe to branch on.

string
message
required

What went wrong, written for a person.

string
detail

Structured particulars, when there are any.

object
key
additional properties
remedy

What to do about it, when there is something to do.

string
requestId
required

Quote this when asking about a specific failure.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"detail": {
"additionalProperty": "example"
},
"remedy": "example",
"requestId": "example"
}
}

The request conflicts with the current state.

Media typeapplication/json
object
error
required
object
code
required

A stable identifier for the kind of failure. Safe to branch on.

string
message
required

What went wrong, written for a person.

string
detail

Structured particulars, when there are any.

object
key
additional properties
remedy

What to do about it, when there is something to do.

string
requestId
required

Quote this when asking about a specific failure.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"detail": {
"additionalProperty": "example"
},
"remedy": "example",
"requestId": "example"
}
}

The request did not match the expected shape.

Media typeapplication/json
object
error
required
object
code
required

A stable identifier for the kind of failure. Safe to branch on.

string
message
required

What went wrong, written for a person.

string
detail

Structured particulars, when there are any.

object
key
additional properties
remedy

What to do about it, when there is something to do.

string
requestId
required

Quote this when asking about a specific failure.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"detail": {
"additionalProperty": "example"
},
"remedy": "example",
"requestId": "example"
}
}

Rate limited. Retry after the interval in the header.

Media typeapplication/json
object
error
required
object
code
required

A stable identifier for the kind of failure. Safe to branch on.

string
message
required

What went wrong, written for a person.

string
detail

Structured particulars, when there are any.

object
key
additional properties
remedy

What to do about it, when there is something to do.

string
requestId
required

Quote this when asking about a specific failure.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"detail": {
"additionalProperty": "example"
},
"remedy": "example",
"requestId": "example"
}
}

GitHub or another dependency refused or did not answer. Nothing in the workspace changed.

Media typeapplication/json
object
error
required
object
code
required

A stable identifier for the kind of failure. Safe to branch on.

string
message
required

What went wrong, written for a person.

string
detail

Structured particulars, when there are any.

object
key
additional properties
remedy

What to do about it, when there is something to do.

string
requestId
required

Quote this when asking about a specific failure.

string
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"detail": {
"additionalProperty": "example"
},
"remedy": "example",
"requestId": "example"
}
}