EncoreService
plany.encore.v1.EncoreService — publisher links, Encores, transfers, offers, purchases, and the four calls a player's game makes.
Global: one endpoint for every region, because an Encore belongs to your account.
Two kinds of caller. A developer — through an API key or a session — links a publisher, declares an Encore, transfers its game and prices its offers. A player's game, with no credential at all, calls the four public methods, usually through their JSON equivalents. Reviews, outstanding limits and settlements are decided by Plany, and you see their effects on the resources below.
A call you lack permission for is answered NOT_FOUND, so nobody can learn which
Encores exist from the difference.
Distributor links
accounts/{account}/distributorLinks/{distributor_link}
| Method | Request → Response | Notes |
|---|---|---|
CreateDistributorLink | → DistributorLink | The key is checked with Steam before anything is stored, and its listings read. A rejected key, or one that owns no game, is INVALID_ARGUMENT; Steam not answering is UNAVAILABLE. |
GetDistributorLink | → DistributorLink | Never carries the key; carries its fingerprint, outstanding, reserved and outstanding_limit. |
ListDistributorLinks | → ListDistributorLinksResponse | |
UpdateDistributorLink | → DistributorLink | display_name and steam.publisher_key. A new key must still own every game an Encore on the link sells (KEY_DOES_NOT_OWN_PRODUCT), and rotating clears STATE_CREDENTIAL_INVALID. |
DeleteDistributorLink | → Empty | Refused with LINK_IN_USE while an Encore names the link or any purchase has been made through it. |
ListSettlements | → ListSettlementsResponse | What you have paid Plany for credit already issued. |
Permissions: encore.links.create / .get / .list / .update / .delete.
ListSettlements takes .get. Held by account.owner and account.billing;
account.admin and account.viewer read only.
steam.sandbox is immutable: it sends every order to Steam's microtransaction sandbox,
credits nothing and needs no outstanding limit. See Linking Steam.
Encores
accounts/{account}/encores/{encore}
| Method | Request → Response | Notes |
|---|---|---|
CreateEncore | → Encore | Returns at once in STATE_VERIFYING. game must be this account's own; listing must be one of the link's; funding_visibility is required with no working zero value. One Encore per app on the platform (PRODUCT_ALREADY_HAS_ENCORE). |
GetEncore | → Encore | Carries encore_key, verification, project and transfer. |
ListEncores | → ListEncoresResponse | filter accepts state = "NEEDS_REVIEW" (or another state) and nothing else. |
UpdateEncore | → Encore | display_name and funding_visibility. Pass etag to refuse a stale write as ABORTED. |
DeleteEncore | → Empty | Refused with ENCORE_TRANSFERRED once a transfer has been started or any purchase made. |
RetryVerification | → Encore | From NEEDS_REVIEW or DECLINED only; otherwise NOT_RETRYABLE. |
GetFunding | → Funding | Balance, seven-day spend, runway, and purchases over the window. |
Permissions: encore.encores.create / .get / .list / .update / .delete;
RetryVerification takes .update; GetFunding takes encore.funding.get, which
travels with billing visibility rather than with the game.
The verification policy is two outcomes, never three: VERIFIED when the linked key
owns the app and the store no longer sells it or your own Steam announcement says it
is ending; NEEDS_REVIEW otherwise. See Verification.
Transfers
| Method | Request → Response | Notes |
|---|---|---|
PlanTransfer | → TransferPlan | Changes nothing. Every candidate in source_project, in every region, with belongs_to_game, client_facing and movable; a recommended_mode, an explanation and the warnings. Anything that cannot be listed makes the plan recommend MOVE. |
StartTransfer | → Operation | MODE_CONVERT re-plans and is refused with CANNOT_CONVERT unless the fresh plan recommends it; completes in the call. MODE_MOVE requires resources and acknowledge_warnings, and runs in the background. Metadata is the Transfer; the response is the Encore. Idempotent on request_id. |
AcknowledgeTransferItem | → Encore | Accepts moving one item — a stopped server whose disk cannot be copied — as a fresh install. NOT_AWAITING_ACKNOWLEDGEMENT for anything else. |
Permissions: encore.transfers.start on the Encore, and project.projects.update
on the source project. Not implied by encore.encores.update: a transfer is a one-way
decision about infrastructure. Held by account.owner and account.admin, deliberately
not by account.billing. See Transferring.
Refusals: ALREADY_TRANSFERRED, TRANSFER_RUNNING, WARNINGS_NOT_ACKNOWLEDGED.
Offers
accounts/{account}/encores/{encore}/offers/{offer}
| Method | Request → Response | Notes |
|---|---|---|
CreateOffer | → Offer | price is USD in whole cents. credit is USD and at most the price less the storefront's share. display_name is what the overlay shows. |
GetOffer / ListOffers | → | |
UpdateOffer | → Offer | display_name, description, price, credit, active. A price change applies to purchases begun afterwards. |
DeleteOffer | → Empty | An offer somebody bought is deactivated instead. |
Permissions: encore.offers.create / .get / .list / .update / .delete.
Purchases
accounts/{account}/encores/{encore}/purchases/{purchase}
| Method | Request → Response | Notes |
|---|---|---|
GetPurchase | → Purchase | |
ListPurchases | → ListPurchasesResponse | Newest first. |
There is no create: a purchase is made by a player's game. Permissions:
encore.purchases.get / .list. See Offers and purchases.
Anonymous: a player's game
No credential. Named by encore_key; a purchase is proven by a Steam Web API ticket
checked with the studio's own key. Each is also served as HTTPS/JSON at
https://encore.plany.cloud, which is what the SDKs use.
| Method | JSON | Notes |
|---|---|---|
GetPublicFunding | POST /v1/public/funding:get | Shaped by funding_visibility. Names no account. |
ListPublicOffers | POST /v1/public/offers:list | Active offers, even before verification, with purchasable false. |
BeginPurchase | POST /v1/public/purchases:begin | Opens the Steam order. Refused before Steam is called when the Encore is not verified or transferred, the offer is inactive, or the outstanding limit would be exceeded. Idempotent on request_id for the same player. |
CompletePurchase | POST /v1/public/purchases:complete | Settles. Safe to repeat or to skip; a decline is confirmed with Steam. |
The price, the credit and the project are never taken from the request. Named
refusals carry a google.rpc.ErrorInfo reason: ENCORE_NOT_VERIFIED,
ENCORE_NOT_READY, OFFER_INACTIVE, PUBLISHER_LIMIT_REACHED,
PUBLISHER_UNAVAILABLE, ORDER_REFUSED, PLAYER_NOT_AUTHENTICATED. See
Refusals.
Related, in billing
plany.billing.v1.BillingService/CreateCheckoutSession takes an optional project,
which buys credit for a top-up-only project rather than for the account — how you fund
an Encore project yourself. A player's purchase appears in ListLedgerEntries as a
TYPE_PLAYER_TOP_UP entry. See Funding.