Skip to content
Publishing works: space publish mints one immutable marketplace revision, a buyer reviews a fixed quote against it, and an order reaches placed on a runner in the project. Everything after placement is labeled agreed direction on this page, and no order has been observed through to a result.

Publishing to the marketplace

A buyer who orders your application needs to know that the bytes they pay for are the bytes you tested, and that your next release does not change the order they already placed. Publishing puts a build on the Space Store, the Platform application catalog served at run.space, as an immutable revision pinned to one signed build. The flags and exit statuses are in the CLI reference.

Publication

space publish validates your application manifest, assembles the signed launch material for the declared architecture out of that image's signed build, uploads the blobs it names, and asks the ground selected by --ground to mint one immutable marketplace revision pinned to that image. The launch material is what a node needs to admit and start the image, taken from its signed build: the launch plan, the layer and manifest blobs, each partition's signed capability, and the TUF metadata chain that authorizes their digests.

space build then space publish is the whole chain. Nothing has to have been deployed first. Publishing pushes no OCI image, starts no service, and makes no qualification claim. In space engineering, qualification is the test and review campaign that shows a piece of hardware or software meets a mission's requirements for flight; a qualification assertion is a signed statement that one such test passed, attached separately to an immutable artifact.

Two inputs are required, and the command names both when you give neither:

Terminal window
$ space publish
space publish: name the image to publish and the manifest that describes it.
Both are needed: `space publish IMAGE --manifest FILE`.
IMAGE is a reference `space build` produced; FILE declares the profile, the
architecture and the limits of the listing.
[123]

The bracketed number on the last line is the exit status: every space command exits 123 on a refusal, and the CLI reference lists the others.

Give the image alone and the refusal names it back, so you type the manifest against the image you meant:

Terminal window
$ space publish registry.example/cloud-mask:1
space publish: name the application manifest for
registry.example/cloud-mask:1.
Try `space publish registry.example/cloud-mask:1 --manifest FILE`.
FILE declares the target profile, the architecture and the limits the listing
carries.
[123]

Application manifest

The application manifest is the contract the listing carries. It declares the supported target profile and architecture, the runtime isolation, the input and result schemas, the execution limits, the cancellation policy, and the support owner.

Everything a buyer is shown about your application, and everything their order is checked against, comes from that document. A manifest declaring an architecture no image in the publication supplies is refused: the revision's launch material is assembled from a signed build, so every architecture the manifest claims needs its own IMAGE argument.

space publish --plan validates the manifest and the image bindings and prints the publication plan without building, reading credentials, or writing remote state. Read the plan before you mint anything.

Revisions

Each publication mints one revision, and a revision is immutable. It is pinned to one signed build, so the bytes a buyer orders are the bytes you published. Publishing again mints the next revision on the same listing and names the one it replaces.

Nothing edits a revision in place. That is what lets an order keep its meaning after you publish again, and it is why a listing's history is a chain of revisions.

Publishing is not deploying. space publish offers a build to buyers; space deploy ships a release to a target you connected. The two take different credentials and answer to different people.

Orders against a revision

A published revision appears in the catalog on run.space. A buyer selects it, states the area and the time window they need, and reviews a fixed quote that pins the invocation, the revision, the chosen acquisition where there is one, and one total. Accepting that quote places one durable order, and the order reaches placed against a runner in the project.

That is the boundary today. Each step below is agreed direction, and it keeps its label until it works:

  • An order completes and its timeline reaches a final state [roadmap].
  • You download the result and check its result manifest against the output contract the revision published [roadmap].
  • The order carries a completion certificate a stranger can re-check without your credentials [roadmap].
  • A priced listing authorizes payment through the provider before the work is released, and a free listing records that no payment was required [roadmap].

Publish at a price of zero while those steps carry a label. Buyers of a listing minted with --price-usd-c above zero reach the boundary this page describes.

Demand

A listing carries a reading of its own demand: the orders placed against it over a period you state, counted by state, and what those orders earned, one amount per currency in minor units. The project's publish tab on run.space draws that panel, and it states the period it is showing above the numbers.

The same answer is one request. GET /api/v0/marketplace/apps/LISTING/demand takes from and until as RFC 3339 date-times and answers for a listing your own account published. Every value in it is your listing's and the period's, so the document below shows the shape of the answer:

{
"listing": "app-watch",
"from": "2026-08-01T00:00:00Z",
"until": "2026-09-01T00:00:00Z",
"orders": [
{ "state": "completed", "count": 2 },
{ "state": "refused", "count": 1 }
],
"revenue": [
{ "minor": 300, "currency": "EUR" },
{ "minor": 1200, "currency": "USD" }
]
}

The request states the period, and one that carries fewer than both edges is refused and says so. A listing another account published is refused as not found, the same answer a listing nobody published gets, so a caller cannot learn whether another account has published a listing under that name.

Nothing in that answer names a buyer. An order belongs to the person who placed it, and the counts and the amounts are facts about your listing, so the answer carries no rows, no addresses and no order ids. No space command reads it.

Revenue counts the orders that completed, because that is the only state in which a buyer received what they bought. While completion carries its label above [roadmap], a listing's revenue reads zero and its demand is read from the counts beside it. Currencies are never added: an amount in one is not an amount in another without a rate.

Publishing credential

Publishing addresses a ground by URL. Run space login URL --flow device --scope publish:LISTING to obtain a credential under that ground's origin, then pass --ground URL to space publish. The device flow is the OAuth device authorization grant (RFC 8628): the CLI prints a short code, you approve it in a browser on any machine, and the CLI polls the ground until it receives the credential. A credential is scoped to what it may do, and the refusal names the scope a publication takes when the credential you hold is the wrong one.

The CLI reference lists sign-in options, and the signing chapter covers the keys that sign the build a revision pins.