`POST /api/marketplace/bundles/publish` — publish several workspace primitives as one `kind='bundle'` item. Workspace-admin only, like every other publish path.
const url = 'https://example.com/api/marketplace/bundles/publish';const options = { method: 'POST', headers: {'Content-Type': 'application/json'}, body: '{"app_ids":["2489E9AD-2EE2-8E00-8EC9-32D5F69181C0"],"categories":["example"],"changelog":"example","description":"example","name":"example","node_type_ids":["2489E9AD-2EE2-8E00-8EC9-32D5F69181C0"],"prerequisites":"example","prerequisites_de":"example","prerequisites_must_acknowledge":true,"pricing":{"amount_minor":1,"currency":"example","model":"example"},"required_resource_kinds":["example"],"script_ids":["2489E9AD-2EE2-8E00-8EC9-32D5F69181C0"],"slug":"example","summary":"example","tags":["example"],"version":"example","workflow_ids":["2489E9AD-2EE2-8E00-8EC9-32D5F69181C0"]}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://example.com/api/marketplace/bundles/publish \ --header 'Content-Type: application/json' \ --data '{ "app_ids": [ "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0" ], "categories": [ "example" ], "changelog": "example", "description": "example", "name": "example", "node_type_ids": [ "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0" ], "prerequisites": "example", "prerequisites_de": "example", "prerequisites_must_acknowledge": true, "pricing": { "amount_minor": 1, "currency": "example", "model": "example" }, "required_resource_kinds": [ "example" ], "script_ids": [ "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0" ], "slug": "example", "summary": "example", "tags": [ "example" ], "version": "example", "workflow_ids": [ "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0" ] }'Request Bodyrequired
Section titled “Request Bodyrequired”Body for POST /api/marketplace/bundles/publish.
At least two primitives across the four id lists must be named — a
single-primitive “bundle” is that primitive’s own listing and belongs on its
own publish path. version defaults to 1.0.0.
object
Workspace App ids to fold in. Each ships its full source tree embedded in the manifest, so the bundle installs on a bare instance.
#1060 - Markdown describing what changed in THIS bundle version. See
[super::marketplace_publish_dto::PublishRequest::changelog]: the column
has had a UI tab but no producer since migration 094, and a bundle needs
one as much as a single item does.
#943 - Markdown describing what the buyer must set up on their OWN systems before this bundle can work. English.
#943 - the German mirror of prerequisites.
#943 - when true the installer must tick the acknowledgement before the install action unlocks. Enforced server-side, not only in the wizard.
Seller-declared price on a publish request. model is the publish-facing
vocabulary (free | one_time | monthly); an absent currency defaults
to EUR. Shared by every publish handler (app / script / workflow / node).
monthly is the ONLY recurring word, and it maps to the single recurring
price model — see [map_publish_pricing].
object
Resource kinds the installer must bind for the product as a whole. The kinds a member connector declares are merged in automatically.
Examplegenerated
{ "app_ids": [ "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0" ], "categories": [ "example" ], "changelog": "example", "description": "example", "name": "example", "node_type_ids": [ "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0" ], "prerequisites": "example", "prerequisites_de": "example", "prerequisites_must_acknowledge": true, "pricing": { "amount_minor": 1, "currency": "example", "model": "example" }, "required_resource_kinds": [ "example" ], "script_ids": [ "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0" ], "slug": "example", "summary": "example", "tags": [ "example" ], "version": "example", "workflow_ids": [ "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0" ]}Responses
Section titled “Responses”A catalog item — an app, script, bundle, or runner offer listing.
Scoped to a source via source_id. The (source_id, slug) pair is unique.
object
ADR 0030 W6 — build framework of the item’s latest non-withdrawn
version (plain | react | svelte). Populated by list_items /
get_item via a correlated subquery; absent in queries that do not
project it (e.g. upsert_item RETURNING), where #[sqlx(default)]
supplies "plain". Surfaces a framework badge on browse cards.
Runtime String; the spec narrows it to the closed [MarketplaceFramework].
#358 — public install popularity: the number of DISTINCT workspaces that
have installed this item (marketplace_installs). Populated by
list_items / get_item via a correlated subquery mirroring rating;
absent (None) in projections that do not select it, where
#[sqlx(default)] supplies None.
ADR 0034 P4c — active price of the item’s latest version as a JSON
object {model, amount_minor, currency}, or null when the listing is
free. Populated by list_items / get_item via a correlated subquery;
absent (None) in projections that do not select it (e.g. upsert
RETURNING), where #[sqlx(default)] supplies None.
Runtime stays serde_json::Value; the spec types it as [MarketplaceItemPrice].
object
Publisher metadata bag. Runtime stays serde_json::Value; the spec types it
as Option<MarketplaceItemPublisher> (the FE reads publisher?.name) — a
seed/curated listing can carry a publisher-less (null) bag, so the optional
spec is the honest shape and the FE drops its .extend() defensive widening.
object
ADR 0034 #351 — aggregate CUSTOMER rating of this item as a JSON object
{avg, count} (avg rounded to 2 dp), or null when it has no ratings.
Populated by list_items / get_item via a correlated subquery; absent
(None) in projections that do not select it, where #[sqlx(default)]
supplies None. Distinct from verified (the moderation gate).
Runtime stays serde_json::Value; the spec types it as [MarketplaceItemRatingSummary].
object
Example
{ "framework": "plain"}