Skip to content

Setup API

The Setup API handles first-run instance configuration. All mutating endpoints require a valid setup session token and are permanently disabled after the instance reaches ready state.

For a walkthrough of the setup process, see Set Up Your Instance. For the state machine reference, see Setup States.

Setup Status

Retrieve the current setup state. This endpoint is always public and returns only non-sensitive information.

GET /v1/public/setup-status

Authentication: None (public)

State requirement: Available in all states (including ready)

Response

json
{
  "instance_id": "550e8400-e29b-41d4-a716-446655440000",
  "state": "bootstrap_pending",
  "setup_mode": true,
  "is_configured": false
}
FieldTypeDescription
instance_idstringUUID of this Oore CI instance
statestringCurrent setup state: uninitialized, bootstrap_pending, idp_configured, owner_created, or ready
setup_modebooleantrue when setup is not yet complete
is_configuredbooleantrue when state is ready

Example

bash
curl http://127.0.0.1:8787/v1/public/setup-status

Verify Bootstrap Token

Verify the one-time bootstrap token generated by oore setup token. On success, consumes the token and returns a setup session token.

POST /v1/setup/bootstrap-token/verify

Authentication: None (public)

State requirement: Any state except ready

Request body

json
{
  "token": "a1b2c3d4e5f6..."
}
FieldTypeRequiredDescription
tokenstringYesPlaintext bootstrap token (64 hex characters)

Response 200 OK

json
{
  "session_token": "f7e8d9c0b1a2...",
  "expires_at": 1738800000
}
FieldTypeDescription
session_tokenstringSetup session token for authenticating subsequent requests
expires_atintegerSession expiry as Unix epoch (seconds). Initial TTL is 30 minutes; renewed on each authenticated request.

Error responses

StatusCodeDescription
401invalid_tokenBootstrap token hash does not match
409already_configuredSetup is already complete
410token_consumedBootstrap token has already been used
410token_expiredBootstrap token TTL has elapsed
429too_many_attempts5 or more failed verification attempts
500no_bootstrap_tokenNo bootstrap token has been generated

Example

bash
curl -X POST http://127.0.0.1:8787/v1/setup/bootstrap-token/verify \
  -H "Content-Type: application/json" \
  -d '{"token": "a1b2c3d4e5f6..."}'

Configure OIDC

Configure the OIDC identity provider. Performs provider discovery on the issuer URL and stores the configuration. If a client secret is provided, it is encrypted with AES-256-GCM before storage.

POST /v1/setup/oidc/configure

Authentication: Setup session token (Bearer)

State requirement: bootstrap_pending or idp_configured

Request body

json
{
  "issuer_url": "https://accounts.google.com",
  "client_id": "your-client-id.apps.googleusercontent.com",
  "client_secret": "GOCSPX-your-client-secret"
}
FieldTypeRequiredDescription
issuer_urlstringYesOIDC issuer URL (must support /.well-known/openid-configuration)
client_idstringYesOAuth 2.0 client ID from your identity provider
client_secretstringNoOAuth 2.0 client secret (encrypted at rest if provided)

Response 200 OK

json
{
  "state": "idp_configured",
  "discovered_issuer": "https://accounts.google.com",
  "session_expires_at": 1738801800
}
FieldTypeDescription
statestringNew setup state (idp_configured)
discovered_issuerstringIssuer URL as returned by the OIDC discovery document
session_expires_atinteger | nullUpdated session expiry (sliding window)

Error responses

StatusCodeDescription
400invalid_inputRequest body validation failed
400oidc_discovery_failedCould not fetch or parse the OIDC discovery document
401missing_authAuthorization header not provided
401invalid_sessionSetup session token is invalid
401session_expiredSetup session has expired
409already_configuredSetup is already complete
409invalid_stateNot in bootstrap_pending or idp_configured state
500encryption_errorFailed to encrypt client secret

Example

bash
curl -X POST http://127.0.0.1:8787/v1/setup/oidc/configure \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <session_token>" \
  -d '{
    "issuer_url": "https://accounts.google.com",
    "client_id": "your-client-id.apps.googleusercontent.com",
    "client_secret": "GOCSPX-your-client-secret"
  }'

Start Owner OIDC

Initiate an OIDC authorization code flow to verify the owner's identity. Returns an authorization URL to redirect the user to.

POST /v1/setup/owner/start-oidc

Authentication: Setup session token (Bearer)

State requirement: idp_configured only

Request body

json
{
  "redirect_uri": "http://127.0.0.1:4173/auth/callback"
}
FieldTypeRequiredDescription
redirect_uristringYesURI where the IdP should redirect after authentication

Response 200 OK

json
{
  "authorization_url": "https://accounts.google.com/o/oauth2/v2/auth?client_id=...&redirect_uri=...&state=...&nonce=...",
  "state": "abc123-csrf-state-token"
}
FieldTypeDescription
authorization_urlstringFull authorization URL to redirect the user to
statestringCSRF state token for validating the callback

The daemon generates a PKCE challenge (S256), CSRF state token, and nonce internally. The PKCE verifier and nonce are stored server-side, keyed by the state value. Pending auth entries expire after 10 minutes.

Error responses

StatusCodeDescription
400invalid_redirect_uriThe redirect URI is malformed
401missing_authAuthorization header not provided
401invalid_sessionSetup session token is invalid
401session_expiredSetup session has expired
409already_configuredSetup is already complete
409invalid_stateNot in idp_configured state
429too_many_pendingToo many pending auth requests (limit: 1000)
502oidc_discovery_errorFailed to perform OIDC discovery

Example

bash
curl -X POST http://127.0.0.1:8787/v1/setup/owner/start-oidc \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <session_token>" \
  -d '{"redirect_uri": "http://127.0.0.1:4173/auth/callback"}'

Verify Owner OIDC

Complete the OIDC authorization code flow started by Start Owner OIDC. Exchanges the authorization code for tokens, verifies the ID token, extracts the owner's email and OIDC subject, and creates the owner record.

POST /v1/setup/owner/verify-oidc

Authentication: Setup session token (Bearer)

State requirement: idp_configured only

Request body

json
{
  "code": "4/0AX4XfWh...",
  "state": "abc123-csrf-state-token"
}
FieldTypeRequiredDescription
codestringYesAuthorization code from the IdP callback
statestringYesCSRF state token from the IdP callback (must match the value from start-oidc)

Response 200 OK

json
{
  "state": "owner_created",
  "owner_email": "[email protected]",
  "oidc_subject": "110123456789012345678",
  "session_expires_at": 1738801800
}
FieldTypeDescription
statestringNew setup state (owner_created)
owner_emailstringEmail address extracted from the ID token
oidc_subjectstringOIDC subject identifier from the ID token
session_expires_atinteger | nullUpdated session expiry (sliding window)

Error responses

StatusCodeDescription
400invalid_stateUnknown or expired OIDC state parameter
400auth_expiredOIDC authorization request has expired (10-minute TTL)
401missing_authAuthorization header not provided
401invalid_sessionSetup session token is invalid
401session_expiredSetup session has expired
409already_configuredSetup is already complete
409invalid_stateNot in idp_configured state
500decryption_errorFailed to decrypt stored client secret
500store_errorDatabase operation failed
502oidc_discovery_errorFailed to perform OIDC discovery
502token_exchange_errorFailed to exchange authorization code for tokens
502missing_id_tokenIdP did not return an ID token
502id_token_verification_errorID token signature or claims verification failed
502missing_emailID token does not contain an email claim

Example

bash
curl -X POST http://127.0.0.1:8787/v1/setup/owner/verify-oidc \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <session_token>" \
  -d '{
    "code": "4/0AX4XfWh...",
    "state": "abc123-csrf-state-token"
  }'

Complete Setup

Finalize the setup process. Transitions the instance to ready state, clears the setup session, and permanently disables all setup endpoints.

POST /v1/setup/complete

Authentication: Setup session token (Bearer)

State requirement: owner_created only

Request body

None.

Response 200 OK

json
{
  "state": "ready",
  "instance_id": "550e8400-e29b-41d4-a716-446655440000"
}
FieldTypeDescription
statestringFinal setup state (ready)
instance_idstringUUID of the configured instance

Error responses

StatusCodeDescription
401missing_authAuthorization header not provided
401invalid_sessionSetup session token is invalid
401session_expiredSetup session has expired
409already_configuredSetup is already complete
409invalid_stateNot in owner_created state

Example

bash
curl -X POST http://127.0.0.1:8787/v1/setup/complete \
  -H "Authorization: Bearer <session_token>"

DANGER

This action is irreversible. Once setup is complete, all setup endpoints are permanently disabled.

Self-hosted mobile CI, built for Flutter.