Webhook configuration
OSA Proxy sends HTTP POST notifications when files are downloaded or blocked. Webhook delivery is outside the client request path: a download does not wait for the receiver, and a delivery error does not change the OSA Proxy response.
Notifications are available for all supported ecosystems except Docker. They are created only for GET requests to repository routes. HEAD requests, operational endpoints, and ordinary upstream errors do not create notifications.
Events
If one subscription contains both file_downloaded and scanned_file_downloaded, an evaluated request produces only one notification with trigger: scanned_file_downloaded.
A 200 or 206 status is the response observed by OSA Proxy. It does not confirm that the client received or saved the complete file.
Request format
Each POST contains exactly one event:
Payload fields:
OSA Proxy sends Content-Type: application/json. When a secret is configured, it also sends X-CodeScoring-Authentication. There is no separate request-signature header.
The webhook continues the original request trace. The receiver gets trace headers and the same X-Trace-Id used for upstream and CodeScoring requests.
A test POST differs from an operational notification and checks connectivity only:
The receiver can return any 2xx status. OSA Proxy treats the delivery as successful and ignores the response body.
Configuration in osa-proxy.yml
Without Configuration Store, add subscriptions at the root of osa-proxy.yml. Set token_env to the name of the environment variable containing the token:
Restart every OSA Proxy replica after changing YAML. Give every replica the same subscription and token configuration for consistent behavior.
Subscription parameters
Each enabled subscription has its own bounded queue and one sequential sender. When the queue is full, the new notification is dropped. Every 30 seconds, OSA Proxy writes the accumulated count to the webhook notifications dropped warning log.
Only one delivery attempt is made for each notification. There are no retries or durable storage. Redirects are not followed, so a 3xx response is a delivery failure. Non-2xx responses, timeouts, and network errors produce a webhook delivery failed warning without affecting the client request.
A notification can be lost when a queue is full, the process stops, or the receiver fails. Do not use a webhook as the only audit source or as transactional confirmation of a download.
Receiver authentication
Create a Secret with the receiver token and pass it to OSA Proxy through an environment variable. Then put the variable name in token_env:
Do not put the token value in configuration or the repository. In managed mode, send token_env through the Admin API with the subscription; you do not need to duplicate the webhook in osa-proxy.yml. The API stores and returns only the variable name, never the token.
If the variable is missing or empty, the subscription is not activated. Restart every OSA Proxy replica after adding or changing the Secret.
Connectivity test through Admin API
Admin API uses a separate listener, 127.0.0.1:8081 by default, and a Bearer Admin Token. In Kubernetes, do not expose the admin Service without TLS, an authenticated ingress or reverse proxy, and network restrictions.
You can test an unsaved subscription whether Configuration Store is enabled or not:
Example successful result:
success: true means only that the test POST received a 2xx response. Possible error_category values are invalid_configuration, timeout, connection, and http_status.
Managing subscriptions through Admin API
Subscription CRUD is available only when Configuration Store is enabled. With storage disabled, these endpoints return 503 managed_storage_disabled; use YAML instead. Swagger UI is available at /swagger/, and OpenAPI at /openapi.json on the admin listener.
Main endpoints:
Every mutation uses optimistic concurrency. Get the section ETag first, then pass it unchanged in If-Match:
Copy the ETag header value, including its double quotes:
A successful mutation returns a new ETag. Reusing an old ETag returns 409 section_conflict; repeat GET, inspect the current state, and then deliberately retry the change. Request body fields are validated strictly, and the section is limited to 100 subscriptions.
Testing a saved subscription does not create a revision:
The response contains section_etag, which lets a client detect whether the section changed since it was read.
Troubleshooting
Check these structured log messages:
webhook deliveredat debug level: the receiver returned2xx;webhook delivery failedat warning level: network error, timeout, or non-2xxresponse;webhook notifications droppedat warning level: the subscription queue is full;countis the number dropped during the interval.
If a test endpoint succeeds but no operational event arrives, check the request method, ecosystem, public repository name, enabled, events, OSA Proxy response status, and whether the request was classified as a file or package.
