Publishing
Publishing gives an existing service a Juice interface: a name, a description, typed input and output, a price, and an audience. Registration and activation are separate, so you can prepare that interface before allowing calls.
Creating an action
The following example registers an HTTP endpoint that echoes a message. Its
input schema describes the msg field, and its price is half a credit on
play:
$ juice action create echo --kind http --source https://httpbin.org/post \
--price 0.5 --description "Echo a message back to the caller" \
--input-schema '{"type":"object","properties":{"msg":{"type":"string","description":"text to echo"}},"required":["msg"]}'
id: bb7fe1a8-…
owner_handle: bob
name: echo
kind: http
active: false
visibility: private
price: 0.50 credits
…
quote_hash: 4965342976414282…
Choose a name that is unique among your actions. Slashes let you organize related
operations under a shared path, such as bob/mail/send and bob/mail/inbox.
The shared path also allows later changes to be applied to the group.
The --kind option determines where the implementation runs:
| Kind | --source / --artifact |
Use |
|---|---|---|
http |
--source URL |
an endpoint you already run |
wasm |
--artifact FILE |
code the kernel runs in a sandbox |
For an HTTP action, --method selects the HTTP verb, defaulting to POST.
Use --param when input fields need explicit positions in the URL path or
query. Otherwise, matching arguments fill path placeholders and the remaining
arguments form the request body.
The kernel checks source URLs at creation and activation. By default it permits loopback endpoints but refuses private, link-local, and reserved networks. An operator can widen that policy. Redirects remain subject to the same checks, including redirects from an initially permitted loopback endpoint.
Description and schemas are the contract
The description and schemas serve both people and software. A buyer uses them to judge whether the action suits a task; search uses the description to find it; and an agent uses the input schema to construct arguments. Explain what the service does and describe each field sufficiently for someone unfamiliar with your implementation to use it.
Activation requires a nonempty description and valid schemas. The input schema is checked before funds are reserved, and the output schema before the provider is paid. A result that violates the output schema causes a failed call.
Enabling and choosing an audience
A new action is inactive and private. Enable it to permit execution, then choose who may call it by setting its visibility:
$ juice action enable bob/echo
enabled bob/echo
$ juice action update bob/echo --visibility local
…
visibility: local
| Visibility | Who can call it |
|---|---|
private |
you only |
local |
accounts on this kernel |
public |
anyone, including other kernels |
For an eligible action, public makes it available through federation without
a separate listing or approval procedure. Actions using callers’ delegated
credentials remain local, as explained in the web API chapter.
Visibility and activity can be changed independently. Disabling temporarily prevents all calls while retaining the chosen audience for a later reactivation.
Changing terms
An update can affect the interface, the implementation, or the conditions under which the action is used. Changing its price, either schema, or source deactivates it, resets current statistics, and revokes delegated grants. Reactivation is then an explicit step, and callers must renew any required consent:
$ juice action update bob/echo --price 0.75
$ juice action enable bob/echo
Changing only the description resets statistics but preserves activity and grants. Changing visibility preserves both activity and statistics. Callers who pinned a previous quote must read and accept changed terms before running again. See Pinning the terms you saw.
Retiring an action
$ juice action disable bob/echo
$ juice action delete bob/echo
Use disable when you may want to offer the action again, and delete to
retire it. Retirement removes it from use and listings while preserving its
transactions, receipts, and ratings. Historical transactions retain the action
name needed to interpret them.
Acting on a whole path
The mutation commands accept an action ID for one action, or an owner/path
reference for the action at that path and its descendants. For example,
enabling bob/greeter can enable both operations in an application:
$ juice action enable bob/greeter
enabled bob/greeter/greet
enabled bob/greeter/index
Price, visibility, and credentials can be updated across the selected path. Description, schema, and source changes require a selection resolving to one action, since those fields describe a particular service interface.
Groups and the index convention
The index convention gives a group an entry point. If no action is named
bob/greeter, a caller using that reference reaches bob/greeter/index;
similarly, bob can reach bob/index.
Implement this entry point as an action that describes the group. It has the same price, execution, and rating rules as any other action. The convention therefore provides a common name for related services without requiring a separate application interface.
Upstream credentials you hold
When an upstream service uses your provider account, attach its credential to the action. The kernel will apply it when sending requests to the endpoint:
$ juice action create weather --kind http --source https://api.example.com/v1/forecast \
--price 1 --description "Forecast for a city" \
--input-schema '…' \
--auth '{"scheme":"bearer","secrets":{"token":"…"}}'
Supported schemes include header, query, bearer, basic, OAuth client
credentials, and JWT bearer. Credentials are encrypted in storage and excluded
from readable action details, call data, logs, and receipts. An action read
reports the scheme and whether a caller grant is required. Replacing the
credential revokes associated grants but does not deactivate the action.
If instead each caller must use their own account on the upstream service, see Wrapping a web API.