Skip to main content

Config

The config surface manages three resource families — settings (typed key/value), feature flags, and secrets (write-only values, metadata-only reads) — each available at three scopes: the workspace, a project, or an environment. The same route shapes repeat under each scope prefix. For the model, see Settings & feature flags and Secrets.

Scope prefixes

Every route below is relative to one of these three prefixes ({scope}):

ScopePrefix
Workspace/v1/organizations/{orgId}
Project/v1/organizations/{orgId}/projects/{projectId}
Environment/v1/organizations/{orgId}/projects/{projectId}/environments/{environmentId}

Reads require organization.config.read at workspace scope and project.config.read at project or environment scope; writes require the matching organization.config.write / project.config.write.

Endpoints

MethodPathPermissionDescription
GET{scope}/config/settings*.config.readList settings at exactly this scope
POST{scope}/config/settings*.config.writeCreate a setting
PATCH{scope}/config/settings/{settingId}*.config.writeUpdate a setting's value/description
GET{scope}/config/settings/resolve?key={key}*.config.readResolved read — walks the inheritance chain
GET{scope}/config/feature-flags*.config.readList feature flags
POST{scope}/config/feature-flags*.config.writeCreate a feature flag
PATCH{scope}/config/feature-flags/{flagId}*.config.writeUpdate a flag (enabled, value, description)
GET{scope}/config/secrets*.config.readList secret metadata (never values). Organization scope only: ?scope=all lists across every rung
POST{scope}/config/secrets*.config.writeCreate a secret (write-only value)
POST{scope}/config/secrets/{secretId}/rotate*.config.writeRotate a secret's value
DELETE{scope}/config/secrets/{secretId}*.config.writeRevoke a secret

Setting ids are stg_…, flag ids flg_…, secret ids sec_…. Settings and flags have no DELETE route — item routes accept PATCH only.

Create and update a setting

curl -X POST "https://api.orunbase.com/v1/organizations/org_1f6a3c9e/projects/prj_2d3e4f5a/config/settings" \
-H "Authorization: Bearer $ORUN_CLOUD_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "key": "deploy.max_parallelism", "value": 4, "description": "Cap concurrent deploy steps", "valueType": "number", "visibility": "internal" }'
{
"data": {
"setting": {
"id": "stg_3f4a5b6c",
"orgId": "org_1f6a3c9e",
"projectId": "prj_2d3e4f5a",
"environmentId": null,
"scopeKind": "project",
"key": "deploy.max_parallelism",
"value": 4,
"description": "Cap concurrent deploy steps",
"createdAt": "2026-07-02T10:00:00.000Z",
"updatedAt": "2026-07-02T10:00:00.000Z"
}
},
"meta": { "requestId": "req_2f3a4b5c6d7e", "cursor": null }
}

Update with PATCH {scope}/config/settings/stg_3f4a5b6c and a body of { "value": …, "description": …, "valueType": …, "visibility": … } — an omitted valueType/visibility keeps the stored declaration.

valueType is one of string | number | boolean | json (default json); visibility is public | internal | masked (default internal). Invalid enum values are 422 validation_failed field errors, and the value is validated against the declared type (a 422 on the value field on mismatch). Note that valueType and visibility are request-only today: they are accepted and enforced on create/update but not echoed back in responses — the setting objects above carry no such fields.

Resolve a setting through the inheritance chain

GET {scope}/config/settings is the management view — it returns only what is defined at exactly that scope. The resolve endpoint answers "what value applies here": it walks the chain environment → project → workspace → account → default and returns the first match, with provenance.

curl "https://api.orunbase.com/v1/organizations/org_1f6a3c9e/projects/prj_2d3e4f5a/environments/env_6a7b8c9d/config/settings/resolve?key=deploy.max_parallelism" \
-H "Authorization: Bearer $ORUN_CLOUD_TOKEN"
{
"data": {
"setting": {
"id": "stg_3f4a5b6c",
"orgId": "org_1f6a3c9e",
"projectId": "prj_2d3e4f5a",
"environmentId": null,
"scopeKind": "project",
"key": "deploy.max_parallelism",
"value": 4,
"description": "Cap concurrent deploy steps",
"overridable": true,
"inheritedFrom": { "scopeKind": "project" },
"createdAt": "2026-07-02T10:00:00.000Z",
"updatedAt": "2026-07-02T10:00:00.000Z"
}
},
"meta": { "requestId": "req_3a4b5c6d7e8f", "cursor": null }
}

inheritedFrom.scopeKind names the rung the value was found at; overridable: false marks a locked account-scope guardrail that lower scopes cannot override. The key query parameter is required.

Create and rotate a secret

curl -X POST "https://api.orunbase.com/v1/organizations/org_1f6a3c9e/projects/prj_2d3e4f5a/environments/env_6a7b8c9d/config/secrets" \
-H "Authorization: Bearer $ORUN_CLOUD_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: create-stripe-key-01" \
-d '{ "secretKey": "STRIPE_API_KEY", "value": "sk_live_…", "displayName": "Stripe API key" }'
{
"data": {
"secret": {
"id": "sec_4b5c6d7e",
"orgId": "org_1f6a3c9e",
"projectId": "prj_2d3e4f5a",
"environmentId": "env_6a7b8c9d",
"scopeKind": "environment",
"secretKey": "STRIPE_API_KEY",
"displayName": "Stripe API key",
"status": "active",
"version": 1,
"rotationPolicy": null,
"lastRotatedAt": null,
"expiresAt": null,
"createdBy": "usr_9f8e7d6c",
"createdAt": "2026-07-02T10:05:00.000Z",
"updatedAt": "2026-07-02T10:05:00.000Z"
}
},
"meta": { "requestId": "req_4b5c6d7e8f9a", "cursor": null }
}
warning

Secret value is write-only. It is encrypted in the worker before persistence and never appears in any response, event, or audit payload — list and item responses carry metadata only.

Rotate by POSTing the replacement value; the metadata response reflects the bumped version and lastRotatedAt:

curl -X POST "https://api.orunbase.com/v1/organizations/org_1f6a3c9e/projects/prj_2d3e4f5a/environments/env_6a7b8c9d/config/secrets/sec_4b5c6d7e/rotate" \
-H "Authorization: Bearer $ORUN_CLOUD_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "value": "sk_live_new…" }'

Revoke with DELETE {scope}/config/secrets/{secretId}.

List secret metadata across all rungs

On the organization scope only, GET /v1/organizations/{orgId}/config/secrets?scope=all lists metadata for every rung the workspace owns — workspace, project, and environment rows in one paginated read (what the console's Secrets surface renders by default). The parameter fails closed with two 422 validation_failed shapes:

  • scope: ["must be 'all' when present"] — any value other than all;
  • scope: ["'all' is only valid on the organization scope"]?scope=all on a project or environment route.

Use the SDK

The SDK exposes each family as one flat method taking a discriminated scope argument instead of nine path permutations:

import { OrunCloud } from "@saas/sdk";

const client = new OrunCloud({
baseUrl: "https://api.orunbase.com",
auth: { kind: "bearer", token: process.env.ORUN_CLOUD_TOKEN! },
});

const scope = {
kind: "environment",
orgId: "org_1f6a3c9e",
projectId: "prj_2d3e4f5a",
environmentId: "env_6a7b8c9d",
} as const;

const { settings } = await client.config.listSettings(scope);

const { secret } = await client.config.createSecretMetadata(scope, {
secretKey: "STRIPE_API_KEY",
value: "sk_live_…",
});
await client.config.rotateSecret(scope, secret.id, { value: "sk_live_new…" });