Begin Continue with GitHub
const url = 'https://api.pealboard.com/auth/github/start?client=web&codeChallengeMethod=S256';const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}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.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Query Parameters
Section titled “Query Parameters”mobile hands the session back through pealboard://.
mobile hands the session back through pealboard://.
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.
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.
S256 only. plain is a challenge an interceptor can also compute.
S256 only. plain is a challenge an interceptor can also compute.
Responses
Section titled “Responses”A redirect to GitHub’s authorization screen.
No valid credentials.
object
object
A stable identifier for the kind of failure. Safe to branch on.
What went wrong, written for a person.
Structured particulars, when there are any.
object
What to do about it, when there is something to do.
Quote this when asking about a specific failure.
Examplegenerated
{ "error": { "code": "example", "message": "example", "detail": { "additionalProperty": "example" }, "remedy": "example", "requestId": "example" }}Authenticated, but not permitted.
object
object
A stable identifier for the kind of failure. Safe to branch on.
What went wrong, written for a person.
Structured particulars, when there are any.
object
What to do about it, when there is something to do.
Quote this when asking about a specific failure.
Examplegenerated
{ "error": { "code": "example", "message": "example", "detail": { "additionalProperty": "example" }, "remedy": "example", "requestId": "example" }}No such resource, or it is not visible to you.
object
object
A stable identifier for the kind of failure. Safe to branch on.
What went wrong, written for a person.
Structured particulars, when there are any.
object
What to do about it, when there is something to do.
Quote this when asking about a specific failure.
Examplegenerated
{ "error": { "code": "example", "message": "example", "detail": { "additionalProperty": "example" }, "remedy": "example", "requestId": "example" }}The request conflicts with the current state.
object
object
A stable identifier for the kind of failure. Safe to branch on.
What went wrong, written for a person.
Structured particulars, when there are any.
object
What to do about it, when there is something to do.
Quote this when asking about a specific failure.
Examplegenerated
{ "error": { "code": "example", "message": "example", "detail": { "additionalProperty": "example" }, "remedy": "example", "requestId": "example" }}The request did not match the expected shape.
object
object
A stable identifier for the kind of failure. Safe to branch on.
What went wrong, written for a person.
Structured particulars, when there are any.
object
What to do about it, when there is something to do.
Quote this when asking about a specific failure.
Examplegenerated
{ "error": { "code": "example", "message": "example", "detail": { "additionalProperty": "example" }, "remedy": "example", "requestId": "example" }}Rate limited. Retry after the interval in the header.
object
object
A stable identifier for the kind of failure. Safe to branch on.
What went wrong, written for a person.
Structured particulars, when there are any.
object
What to do about it, when there is something to do.
Quote this when asking about a specific failure.
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.
object
object
A stable identifier for the kind of failure. Safe to branch on.
What went wrong, written for a person.
Structured particulars, when there are any.
object
What to do about it, when there is something to do.
Quote this when asking about a specific failure.
Examplegenerated
{ "error": { "code": "example", "message": "example", "detail": { "additionalProperty": "example" }, "remedy": "example", "requestId": "example" }}