Bundles
POST
/v1/orgs/{org_id}/projects/{project_id}/envs/{env_name}/bundles/publishPublish Bundle
Publish a new policy bundle for an environment.
CI tokenscope: bundle:publishoperation_id: bundles.publish
Authentication
Create via POST /v1/orgs/{org_id}/tokens/ci. Project-scoped, allows bundle lifecycle.
SDK install
pip install znyx-sdknpm install @znyx/sdkPath parameters
| Name | Type | Required | Description |
|---|---|---|---|
| org_id#path | string | required | — |
| project_id#path | string | required | — |
| env_name#path | string | required | — |
Header parameters
| Name | Type | Required | Description |
|---|---|---|---|
| X-API-Key#header | string | null | optional | — |
| authorization#header | string | null | optional | — |
Request bodyrequired
| Field | Type | Required | Description |
|---|---|---|---|
| policies | object | required | The resolved policy configuration |
| published_by | string | optional | — |
Responses
| Status | Description |
|---|---|
| 200 | Successful Response |
| 422 | Validation Error |
Response schema
idrequiredstring
versionrequiredinteger
policy_hashrequiredstring
is_activerequiredboolean
published_byrequiredstring | null
published_atrequiredstring
Errors & what triggers them
| Code | Trigger | Fix |
|---|---|---|
| 403 | Token lacks the `bundle:publish` scope (runtime tokens are rejected). | Use a CI token (POST /v1/orgs/{org_id}/tokens/ci) or an admin token. |
| 404 | Project or environment does not exist in the org. | — |
| 422 | Bundle version quota (per plan) exceeded for the environment. | Delete old versions via the Bundles page or upgrade your plan. |
| 500 | Policy signing failed (missing or malformed signing key). | Contact support — this is an operator-side configuration issue. |
Notes & examples
Why bundles
Runtimes don't read policies directly from the database. They fetch signed bundles — a snapshot of the resolved policy for a specific (project, environment), stamped with a hash and signed. This gives you:
- Atomic rollouts — one publish == one version the runtime can pin to.
- Tamper evidence — the runtime verifies the signature.
- CI/CD friendliness — publish in CI, promote to staging, promote to prod on approval.
Typical CI flow
# After policy changes land on main:
curl -X POST \
https://api.znyx.ai/v1/orgs/$ORG/projects/$PROJ/envs/dev/bundles/publish \
-H "Authorization: Bearer $ZNYX_CI_TOKEN" \
-d '{ "policies": { ... }, "published_by": "ci" }'
# ...after smoke tests pass:
curl -X POST \
https://api.znyx.ai/v1/orgs/$ORG/projects/$PROJ/envs/dev/promote \
-H "Authorization: Bearer $ZNYX_CI_TOKEN"The promote endpoint flips dev → staging → prod. Direct activate is also available if you need to pin a specific older version.
Webhook events
Every publish/activate/promote emits a webhook event you can subscribe to. Use these for CI-to-CI handoff, Slack notifications, or feeding your SIEM.
bundle.publishedbundle.activatedbundle.promoted
Related
POST .../bundles/{version}/activate— pin a specific version.POST .../envs/{source}/promote— move active bundle forward (dev → staging → prod).GET /v1/bundles/latest— runtime fetch.
Request
curl -X POST 'https://api.znyx.ai/v1/orgs/00000000-0000-0000-0000-000000000000/projects/00000000-0000-0000-0000-000000000000/envs/prod/bundles/publish' \
-H 'Authorization: Bearer $ZNYX_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"policies": {},
"published_by": "ui"
}'Response
application/json
Successful Response
{
"id": "string",
"version": 0,
"policy_hash": "string",
"is_active": false,
"published_by": null,
"published_at": "string"
}Schema: object