POST /config/apply
Apply a config-as-code document (idempotent upsert by config_key)
Validates the whole document, then upserts services/metrics/SLOs/pages it names. Use ?dryRun=true to get the diff without changing anything (run on PRs); ?prune=true also deletes config-managed objects absent from the document. Body is YAML (text/yaml) or JSON.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
dryRun | query | no | boolean | |
prune | query | no | boolean |
Request body
{}
Example request
curl -X POST "/api/v1/config/apply" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d "{}"
Responses
200: applied (or planned)
{}
400: invalid request
title: invalid_body. The body is not valid JSON.
401: missing or invalid bearer token
title: unauthenticated. No bearer token was sent, or the key is
invalid or revoked. detail distinguishes the two.
403: missing required scope
title: forbidden. The key is valid but does not carry
write:config.
413: payload too large
title: payload_too_large. The document exceeds the 1 MB limit.
422: document failed validation
title: config_invalid. The document parsed and was structurally
valid JSON, but its contents failed validation. Nothing is applied.
429: rate limit exceeded
title: rate_limited. A burst or daily limit was exceeded;
detail names which. The body carries retry_after in seconds.
500: internal error
title: internal_error. An unhandled server error. Safe to retry.
Every error is an RFC 7807 problem detail served as
application/problem+json:
{
"type": "https://observer.example/problems/forbidden",
"title": "forbidden",
"status": 403,
"detail": "missing scope: write:config"
}
Branch on title, not on detail. See
Errors and status codes for the full
catalogue and the rate-limit headers.