Web API, Webhooks, Automation, Provisioning, and Policy as Code: Core Concepts and Mental Model
Turn SonarQube automation into an auditable control plane by separating API identity, documented endpoint/version, request state, asynchronous analysis state, webhook events, and policy ownership.
Learning objectives
- Separate automation identity, authentication, endpoint/version, HTTP request/response, persisted policy state, asynchronous analysis state, and webhook delivery state.
- Explain why Web API V2 is a gradual endpoint-by-endpoint migration rather than a global URL prefix change.
- Use bearer-authenticated User tokens for Web API automation and preserve token-expiration metadata without exposing the token.
- Recognize pagination, error bodies, idempotency, reconciliation, task IDs, and audit evidence as first-class automation concerns.
- Explain what a SonarQube webhook proves, what it does not prove, and why HMAC validation belongs at the receiver trust boundary.
-
Keep scanner/report upload,
ceTaskId, Compute Engine completion, analysis result, gate state, webhook state, and downstream automation outcome independent.
1. The practical problem: automation can make a wrong action repeatable
Chapter 22 secured the network and identity boundaries around SonarQube. Chapter 23 moves one layer higher: using documented APIs and webhooks to manage projects and policy repeatedly. The danger is that a manual mistake usually affects one operation, while an automation mistake can affect every project every time it runs.
A safe SonarQube automation is therefore not “a curl command that returned 200.” It is a control that can prove who acted, which documented endpoint/version was used, what state existed before the request, what mutation was intended, what response occurred, and what independent state proves the requested outcome.
automation identity → bearer token → documented API endpoint →
read current state → planned mutation → HTTP result → verify
persisted state → audit record
2. Two automation paths: command path and event path
flowchart TD A[Automation identity] -->|Bearer token| B[Documented Web API] B --> C[Read / mutate project policy] C --> D[Persisted SonarQube state] E[Scanner report] --> F[Compute Engine] F --> G[Analysis / gate result] G --> H[SonarQube webhook] H -->|HMAC-signed POST| I[Local / CI receiver] I --> J[Validated event record]
The Web API path is request/response automation initiated by a client. The webhook path is asynchronous event delivery initiated by SonarQube. They meet around project and analysis state, but they have different identities, failure modes, and trust controls.
3. State map to define before automation
Identity state
User that owns the token, global/project permissions, token type, expiration, revocation status, and the secret store that supplies it.
API state
Endpoint path, API generation, HTTP method, content type, request parameters/body, pagination model, documented status/error schema, and deprecation state.
Mutation state
Project key, current existence/visibility, gate/profile/settings/webhooks, expected owner, and whether the operation is create-only or reconciled.
Analysis state
Revision, scanner parameters, report upload,
ceTaskId, Compute Engine result, analysis ID,
Quality Gate status, and resulting project measures/issues.
Webhook state
Webhook key/name, URL, secret presence, latest delivery status, task ID in payload, HMAC header, receiver decision, and replay/deduplication record.
4. Web API V1 and V2: migrate endpoint by endpoint
Current Community Build documentation says Web API V2 will
gradually replace the existing Web API as
individual endpoints are deprecated and replaced. That means there
is no safe rule such as “prepend /api/v2 to every old
path.” Some capabilities already expose V2 resources—for example
certain user-management and DevOps-platform translation APIs—while
long-standing local project creation still documents
POST /api/projects/create.
| Unsafe assumption | Safer automation rule |
|---|---|
| “V2 exists, so all V1 endpoints are obsolete.” | Read the documentation shipped with the exact target instance and migrate only when the documented replacement exists. |
| “A V2 path uses the same parameters/statuses as V1.” | Treat each endpoint contract as independent; update request/response adapters and tests. |
| “Undocumented browser endpoints are fine because the UI uses them.” | Use documented public Web APIs only; internal endpoints can change without compatibility guarantees. |
| “One client library can hard-code endpoints forever.” | Centralize endpoint definitions/version assumptions and fail closed when an endpoint contract is unknown. |
5. Bearer authentication: a User token acts with its owner’s permissions
For Web API calls, current Community Build guidance recommends a
User token in the
Authorization: Bearer ... header. A user token can
perform any API action its owner is authorized to perform. This
makes the token useful for automation—and dangerous if the owner is
a global administrator.
# Token value comes from a secret store or local prompt, never source control.
export SONAR_HOST_URL="http://localhost:9000"
read -rsp "Automation user token: " SONAR_API_TOKEN; echo
export SONAR_API_TOKEN
curl --fail-with-body -sS \
-D evidence/headers.txt \
-H "Authorization: Bearer $SONAR_API_TOKEN" \
"$SONAR_HOST_URL/api/server/version" \
-o evidence/server-version.txt
Authenticated Web API responses normally include
SonarQube-Authentication-Token-Expiration. A few
documented endpoints, including authentication validation and
server-version/project-badge endpoints, are exceptions; capture
expiration from a normal authenticated endpoint that supports it.
Never log the Authorization header itself.
6. HTTP method, content type, and error body are part of the contract
Current documentation recommends form data for traditional POST Web
API requests and notes
application/x-www-form-urlencoded as the usual default
unless the endpoint documents another content type. Place mutation
parameters in the request body rather than URLs when possible so
intermediaries and access logs do not unnecessarily capture
sensitive values.
curl --fail-with-body -sS -X POST \
-H "Authorization: Bearer $SONAR_API_TOKEN" \
--data-urlencode "project=sq-ch23-policy-lab" \
--data-urlencode "name=SQ Chapter 23 Policy Lab" \
--data-urlencode "visibility=private" \
"$SONAR_HOST_URL/api/projects/create"
--fail-with-body is useful because it preserves
SonarQube’s response body when an HTTP error occurs. An automation
that throws away the error body and retries cannot distinguish
duplicate-key validation, permission denial, malformed parameters,
rate/load conditions, or server failure.
7. Pagination is a correctness property, not a performance detail
Many search APIs are paginated. A policy client that inspects only
page one can conclude that a rule, project, user, or issue is absent
when it merely lives on a later page. Traditional endpoints commonly
accept page/page-size parameters such as p and
ps and return paging metadata; V2 resources can use
different representations, so read each endpoint schema.
def iter_v1_pages(get_page):
page = 1
while True:
payload = get_page(page)
yield payload
meta = payload.get("paging", {})
index = int(meta.get("pageIndex", page))
size = int(meta.get("pageSize", 0))
total = int(meta.get("total", 0))
if size == 0 or index * size >= total:
break
page += 1
8. Idempotence and reconciliation: read → compare → mutate → verify
Idempotent automation can be run repeatedly and converge on the same intended state without creating duplicates or amplifying side effects. The safest pattern is a reconciliation loop:
- Read current state with a documented read endpoint.
- Normalize only the fields your automation owns.
- Compare desired state with current state.
- Skip when they match.
- Apply the smallest mutation when they differ.
- Read again and verify the result.
- Record what changed and what was already compliant.
Do not convert every API operation into a retry loop. A create call, delete call, comment creation, or other non-idempotent mutation may need a preflight read, an idempotency key in your own control plane, or explicit reconciliation logic before retry.
9. Webhooks are signed event notifications—not authenticated commands
SonarQube webhooks notify external services when analysis-related
events occur. The payload includes project information, analysis
time, task status/ID, Quality Gate information, and optional
sonar.analysis.* properties. Project and global
webhooks are additive.
Configure a webhook secret and validate
X-Sonar-Webhook-HMAC-SHA256 at the receiver. SonarQube
computes a lower-case HMAC-SHA256 digest of the raw request body. If
the signature does not match, ignore the payload.
10. Asynchronous state still matters after you automate it
scanner exit → report upload → report-task.txt / ceTaskId →
Compute Engine terminal state → analysis persisted → gate result →
webhook delivery → downstream receiver state
A successful API mutation or webhook delivery does not collapse those states into one. The webhook payload itself includes a task ID/status so receivers can correlate the event to server-side processing rather than guessing from CI job state.
11. Read-only inspection before mutation
mkdir -p evidence
curl -fsS "$SONAR_HOST_URL/api/server/version" | tee evidence/version.txt
curl --fail-with-body -sS \
-H "Authorization: Bearer $SONAR_API_TOKEN" \
"$SONAR_HOST_URL/api/components/search?qualifiers=TRK&p=1&ps=100" \
| tee evidence/projects-page-1.json
# Inspect the exact Web API documentation shipped with the instance:
# $SONAR_HOST_URL/web_api
# Record endpoint path, method, permissions, parameters, and changelog before coding a mutation.
Knowledge check
Does Web API V2 mean every old endpoint has a mechanical
/api/v2 replacement?
No. Migration is gradual and endpoint-specific. Use the documentation shipped with the exact target release.
Why should an API client preserve HTTP error bodies?
They distinguish validation, permission, conflict, and server failures that require different corrections; blind retries can repeat the wrong mutation.
What does
SonarQube-Authentication-Token-Expiration help an
automation do?
Track approaching token expiration so dependent jobs can rotate credentials before failure without exposing the token value.
Why must webhook HMAC be calculated over the raw request body?
The sender signs the exact bytes it sent. Parsing and re-serializing JSON can change bytes and produce a different digest.
A valid webhook reports gate ERROR. Should the receiver assume the scanner failed?
No. Scanner/report upload, Compute Engine task status, gate result, and webhook delivery are independent states and must be correlated by revision/task identity.
Official references and version notes
- Community Build — Web API — bearer authentication, token-expiration header, POST form-data guidance, and gradual Web API V2 transition.
- Community Build — managing tokens — User/project/global token semantics, expiration and revocation.
-
Community Build — automating project creation/import
— local project creation through
POST /api/projects/createand examples of current V2 DevOps-platform endpoints. - SonarQube — webhooks — event payload, project/global webhooks, delivery monitoring and HMAC protection.
- SonarQube public Web API reference — webhooks — create/list/update/delete/delivery endpoint family and permission requirements.
- SonarQube public Web API reference — components — documented component discovery/read operations.
- SonarQube downloads — current Community Build/Server/LTA release identities used in the dated compatibility note.
Rechecked 2026-09-08. Mandatory examples target
Community Build 26.9.0.129388 and
SonarScanner CLI 8.1.0.6389. Current Community
Build documentation states that Web API V2 is gradually replacing
the existing Web API endpoint by endpoint; do not infer a
mechanical /api/v2 rewrite. Bearer authentication
with a User token is recommended for Web API calls, and
authenticated responses normally expose
SonarQube-Authentication-Token-Expiration for
rotation planning. Unless an endpoint documents otherwise,
traditional POST Web API calls should use form data /
application/x-www-form-urlencoded. Project creation
remains documented at POST /api/projects/create,
while some newer capabilities already use V2 resources. SonarQube
webhooks can be configured at project/global scope and can be
protected with HMAC-SHA256 in
X-Sonar-Webhook-HMAC-SHA256; validate the raw body
before trusting a payload. Webhook payloads include background
task and Quality Gate evidence, but delivery success is not
equivalent to Compute Engine success or gate pass. Always recheck
the exact target instance’s /web_api documentation,
endpoint changelog, permission requirement, pagination/error
schema, and V2 replacement status before production automation.
ceTaskId, Compute
Engine result, webhook HMAC outcome, task/gate state, controller
version, ownership record, and cleanup/revocation evidence separately.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this
address.