Appearance
Save a settings section draft โ
PUT /v1/admin/site/settings/{section}
- Operation ID:
saveSiteSettingsDraft - Tags: Site settings
- Base URL:
http://localhost:8787
Replaces the section's draft; nothing goes live until it is published. Audited by the database function. The route accepts any of the write permissions, but the database then checks the permission required by the specific section; holding only a non-matching one yields 403 forbidden.
Workflow: Integration guide.
Authentication: staff Bearer JWT with permission site.write or billing.write or settings.write.
Authentication โ
- Auth: staff Bearer JWT (
Authorization: Bearer <access_token>) with the permissions below. - Required permissions:
site.write,billing.write,settings.write
Parameters โ
| Name | In | Type | Required | Description |
|---|---|---|---|---|
section | path | string | yes | One of: "general", "branding", "seo", "auth_ui", "billing", "credits", "limits", "support", "legal", "maintenance" |
Request body โ
Required: yes.
Content type: application/json
Schema: object
| Field | Type | Required | Description |
|---|---|---|---|
draft | object | yes | - |
Responses โ
204 โ
Draft saved.
- Header
x-request-id: Request identifier; quote it when reporting an error. No response body.
Errors โ
400 โ
Request validation failed.
- Header
x-request-id: Request identifier; quote it when reporting an error. Content type:application/json
Schema: object (ValidationErrorBody)
| Field | Type | Required | Description |
|---|---|---|---|
success | boolean | yes | One of: false |
error | object | yes | - |
error.name | string | yes | One of: "ZodError" |
error.issues | object[] | yes | - |
error.issues[].code | string | yes | - |
error.issues[].path | (string | number)[] | yes | - |
error.issues[].message | string | yes | - |
Request validation
json
{
"success": false,
"error": {
"name": "ZodError",
"issues": [
{
"code": "custom",
"path": [
"field"
],
"message": "Invalid value"
}
]
}
}401 โ
Missing, malformed, expired or wrong-audience Bearer token (missing_token, invalid_token, invalid_audience).
- Header
x-request-id: Request identifier; quote it when reporting an error. Content type:application/json
Schema: object (ErrorBody)
| Field | Type | Required | Description |
|---|---|---|---|
error | string | yes | Stable machine-readable error code, e.g. forbidden, not_found. |
details | any | no | Optional structured context. For 403 it is { perm }. |
Error response
json
{
"error": "missing_token"
}403 โ
forbidden: lacks the section-specific write permission.
- Header
x-request-id: Request identifier; quote it when reporting an error. Content type:application/json
Schema: object (ErrorBody), fields as described above.
Error response
json
{
"error": "forbidden",
"details": {
"perm": "site.write | billing.write | settings.write"
}
}404 โ
not_found: unknown section.
- Header
x-request-id: Request identifier; quote it when reporting an error. Content type:application/json
Schema: object (ErrorBody), fields as described above.
Error response
json
{
"error": "not_found"
}500 โ
Unexpected server error (internal). No details are returned.
- Header
x-request-id: Request identifier; quote it when reporting an error. Content type:application/json
Schema: object (ErrorBody), fields as described above.
Error response
json
{
"error": "internal"
}Examples โ
curl โ
bash
curl -X PUT 'http://localhost:8787/v1/admin/site/settings/general' \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H 'Content-Type: application/json' \
--data '{"draft":{}}'TypeScript โ
ts
const accessToken = process.env.ACCESS_TOKEN; // user JWT from your sign-in flow
const response = await fetch("http://localhost:8787/v1/admin/site/settings/general", {
method: "PUT",
headers: {
"Authorization": `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"draft": {}
}),
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
const data = response.status === 204 || response.status === 205
? undefined
: response.headers.get("content-type")?.includes("json")
? await response.json()
: await response.text();