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-statusAuthentication: None (public)
State requirement: Available in all states (including ready)
Response
{
"instance_id": "550e8400-e29b-41d4-a716-446655440000",
"state": "bootstrap_pending",
"setup_mode": true,
"is_configured": false
}| Field | Type | Description |
|---|---|---|
instance_id | string | UUID of this Oore CI instance |
state | string | Current setup state: uninitialized, bootstrap_pending, idp_configured, owner_created, or ready |
setup_mode | boolean | true when setup is not yet complete |
is_configured | boolean | true when state is ready |
Example
curl http://127.0.0.1:8787/v1/public/setup-statusVerify 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/verifyAuthentication: None (public)
State requirement: Any state except ready
Request body
{
"token": "a1b2c3d4e5f6..."
}| Field | Type | Required | Description |
|---|---|---|---|
token | string | Yes | Plaintext bootstrap token (64 hex characters) |
Response 200 OK
{
"session_token": "f7e8d9c0b1a2...",
"expires_at": 1738800000
}| Field | Type | Description |
|---|---|---|
session_token | string | Setup session token for authenticating subsequent requests |
expires_at | integer | Session expiry as Unix epoch (seconds). Initial TTL is 30 minutes; renewed on each authenticated request. |
Error responses
| Status | Code | Description |
|---|---|---|
| 401 | invalid_token | Bootstrap token hash does not match |
| 409 | already_configured | Setup is already complete |
| 410 | token_consumed | Bootstrap token has already been used |
| 410 | token_expired | Bootstrap token TTL has elapsed |
| 429 | too_many_attempts | 5 or more failed verification attempts |
| 500 | no_bootstrap_token | No bootstrap token has been generated |
Example
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/configureAuthentication: Setup session token (Bearer)
State requirement: bootstrap_pending or idp_configured
Request body
{
"issuer_url": "https://accounts.google.com",
"client_id": "your-client-id.apps.googleusercontent.com",
"client_secret": "GOCSPX-your-client-secret"
}| Field | Type | Required | Description |
|---|---|---|---|
issuer_url | string | Yes | OIDC issuer URL (must support /.well-known/openid-configuration) |
client_id | string | Yes | OAuth 2.0 client ID from your identity provider |
client_secret | string | No | OAuth 2.0 client secret (encrypted at rest if provided) |
Response 200 OK
{
"state": "idp_configured",
"discovered_issuer": "https://accounts.google.com",
"session_expires_at": 1738801800
}| Field | Type | Description |
|---|---|---|
state | string | New setup state (idp_configured) |
discovered_issuer | string | Issuer URL as returned by the OIDC discovery document |
session_expires_at | integer | null | Updated session expiry (sliding window) |
Error responses
| Status | Code | Description |
|---|---|---|
| 400 | invalid_input | Request body validation failed |
| 400 | oidc_discovery_failed | Could not fetch or parse the OIDC discovery document |
| 401 | missing_auth | Authorization header not provided |
| 401 | invalid_session | Setup session token is invalid |
| 401 | session_expired | Setup session has expired |
| 409 | already_configured | Setup is already complete |
| 409 | invalid_state | Not in bootstrap_pending or idp_configured state |
| 500 | encryption_error | Failed to encrypt client secret |
Example
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-oidcAuthentication: Setup session token (Bearer)
State requirement: idp_configured only
Request body
{
"redirect_uri": "http://127.0.0.1:4173/auth/callback"
}| Field | Type | Required | Description |
|---|---|---|---|
redirect_uri | string | Yes | URI where the IdP should redirect after authentication |
Response 200 OK
{
"authorization_url": "https://accounts.google.com/o/oauth2/v2/auth?client_id=...&redirect_uri=...&state=...&nonce=...",
"state": "abc123-csrf-state-token"
}| Field | Type | Description |
|---|---|---|
authorization_url | string | Full authorization URL to redirect the user to |
state | string | CSRF 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
| Status | Code | Description |
|---|---|---|
| 400 | invalid_redirect_uri | The redirect URI is malformed |
| 401 | missing_auth | Authorization header not provided |
| 401 | invalid_session | Setup session token is invalid |
| 401 | session_expired | Setup session has expired |
| 409 | already_configured | Setup is already complete |
| 409 | invalid_state | Not in idp_configured state |
| 429 | too_many_pending | Too many pending auth requests (limit: 1000) |
| 502 | oidc_discovery_error | Failed to perform OIDC discovery |
Example
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-oidcAuthentication: Setup session token (Bearer)
State requirement: idp_configured only
Request body
{
"code": "4/0AX4XfWh...",
"state": "abc123-csrf-state-token"
}| Field | Type | Required | Description |
|---|---|---|---|
code | string | Yes | Authorization code from the IdP callback |
state | string | Yes | CSRF state token from the IdP callback (must match the value from start-oidc) |
Response 200 OK
{
"state": "owner_created",
"owner_email": "[email protected]",
"oidc_subject": "110123456789012345678",
"session_expires_at": 1738801800
}| Field | Type | Description |
|---|---|---|
state | string | New setup state (owner_created) |
owner_email | string | Email address extracted from the ID token |
oidc_subject | string | OIDC subject identifier from the ID token |
session_expires_at | integer | null | Updated session expiry (sliding window) |
Error responses
| Status | Code | Description |
|---|---|---|
| 400 | invalid_state | Unknown or expired OIDC state parameter |
| 400 | auth_expired | OIDC authorization request has expired (10-minute TTL) |
| 401 | missing_auth | Authorization header not provided |
| 401 | invalid_session | Setup session token is invalid |
| 401 | session_expired | Setup session has expired |
| 409 | already_configured | Setup is already complete |
| 409 | invalid_state | Not in idp_configured state |
| 500 | decryption_error | Failed to decrypt stored client secret |
| 500 | store_error | Database operation failed |
| 502 | oidc_discovery_error | Failed to perform OIDC discovery |
| 502 | token_exchange_error | Failed to exchange authorization code for tokens |
| 502 | missing_id_token | IdP did not return an ID token |
| 502 | id_token_verification_error | ID token signature or claims verification failed |
| 502 | missing_email | ID token does not contain an email claim |
Example
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/completeAuthentication: Setup session token (Bearer)
State requirement: owner_created only
Request body
None.
Response 200 OK
{
"state": "ready",
"instance_id": "550e8400-e29b-41d4-a716-446655440000"
}| Field | Type | Description |
|---|---|---|
state | string | Final setup state (ready) |
instance_id | string | UUID of the configured instance |
Error responses
| Status | Code | Description |
|---|---|---|
| 401 | missing_auth | Authorization header not provided |
| 401 | invalid_session | Setup session token is invalid |
| 401 | session_expired | Setup session has expired |
| 409 | already_configured | Setup is already complete |
| 409 | invalid_state | Not in owner_created state |
Example
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.