PlanyDocs
Encore

Linking Steam

Connect a Steamworks publisher account, test the whole purchase in the sandbox, and rotate the key.

A distributor link is your publisher account, connected to Plany. It holds the key Plany acts with, the games that key can act for, and the line of credit Plany extends against it.

Encore → Declare a game end of life → Connect Steam publisher → paste the publisher key

The key

A publisher Web API key, not a user key. Create it on the Steamworks partner site under your publisher's Web API settings, and give it Microtransaction permission. A personal key from steamcommunity.com/dev/apikey is refused.

Plany uses it for exactly four things, all on Steam's partner API:

ForSteam call
Which games you ownISteamApps/GetPartnerAppListForWebAPIKey
Who a player isISteamUserAuth/AuthenticateUserTicket, for your app and the identity plany-encore
Opening, settling and reading an orderISteamMicroTxn (or ISteamMicroTxnSandbox)
Refunds and chargebacksISteamMicroTxn/GetReport

The key is checked before anything is saved. A key Steam refuses, or one that can act for no game at all, is refused with INVALID_ARGUMENT. If Steam is not answering at that moment, the call fails with UNAVAILABLE and can simply be retried.

It is never returned. The key is encrypted as soon as Plany receives it, no call reads it back, and it never appears in a log line or an error. It can refund every order your publisher has ever taken, and it is treated that way. What a read does show is steam.publisher_key_fingerprint, so you can see that a rotation happened without anybody seeing the key. In Terraform the key is a write-only argument, so it never reaches your state file either.

Listings

A link's listings are the games its key can act for, read from Steam when the link is created and again whenever the key is rotated.

JSON
"listings": [
{ "distributor": "DISTRIBUTOR_STEAM", "product_id": "4000", "display_name": "Example Arena" }
]

That list is the proof of ownership. An Encore can only name a listing on its link, so nobody can declare a game they do not publish.

product_id is the app id in decimal, as a string.

A game can have exactly one Encore on the whole platform. A second Encore naming the same app is refused with PRODUCT_ALREADY_HAS_ENCORE, so a game's purchases can only ever land in one project.

The sandbox

A sandbox link sends every order to Steam's microtransaction sandbox: the same overlay, nothing charged. Plany credits nothing for a sandbox order and counts nothing against the outstanding limit, which is what lets you run the whole purchase from a build of your game before a single player can buy.

plany encore links create steam-sandbox --sandbox --key-stdin < publisher.key
  • sandbox is fixed when the link is created. Going live is a second link.
  • A sandbox purchase is recorded like any other, with sandbox: true, so you can watch its states in ListPurchases.
  • Because a sandbox link owes nothing, it does not need an outstanding limit to sell. A live link does.
  • A sandbox purchase still needs its Encore verified and transferred, exactly like a live one.

Link your key twice: steam-sandbox for your test builds and steam for the Encore players will buy through. An app can have only one Encore on the whole platform, and an Encore that has taken a purchase — a sandbox one included — cannot be deleted, so do not rehearse on the app id your real Encore will use.

State

stateMeaning
STATE_ACTIVEThe key works and owns at least one game.
STATE_CREDENTIAL_INVALIDSteam refused the key during a purchase. Nothing on this link can sell until the key is rotated; players see PUBLISHER_UNAVAILABLE.

A link notices a revoked key the next time something uses it. The first player to try a purchase afterwards is refused before they are charged, and the link is marked invalid with a message saying so.

Rotating the key

plany encore links rotate steam --key-stdin < new-publisher.key

Three rules:

  1. The new key is checked the way the first one was, and its listings replace the old ones.
  2. It must still own every game an Encore on the link sells. A key that cannot act for one of them is refused with KEY_DOES_NOT_OWN_PRODUCT, naming the game, so a rotation can never move a game's purchases onto somebody else's storefront.
  3. A rotation clears STATE_CREDENTIAL_INVALID. It is the fix for a revoked key, and purchases resume as soon as it returns.

Only display_name and steam.publisher_key can be updated. sandbox cannot.

FieldWhat it is
outstandingCredit Plany has issued to your projects through this link and you have not yet settled. Refunds reduce it.
reservedCredit held for purchases players have started and not finished. Counted against the limit, so two players cannot both take the last of it.
outstanding_limitThe most outstanding + reserved may reach. Set by Plany, and $0 until it is.
distributor_share_basis_pointsSteam's share of a sale, out of 10,000. An offer's credit can be at most its price less this.

Your payments are listed as settlements on the link:

plany encore settlements list --link steam

See Where the money goes.

DeleteDistributorLink (plany encore links delete) is refused with LINK_IN_USE while any Encore names the link, and while any purchase has ever been made through it. A link is also the record of what was owed and paid, and that record is kept.

Who can do what

A link is money: it holds a key that can refund your orders, and it is a line of credit. So creating, rotating and removing one sits with the roles already trusted with the account's money.

RoleLinks
roles/account.ownerEverything.
roles/account.billingCreate, read, rotate, remove.
roles/account.adminRead only.
roles/account.viewerRead only.