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 keyThe 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:
| For | Steam call |
|---|---|
| Which games you own | ISteamApps/GetPartnerAppListForWebAPIKey |
| Who a player is | ISteamUserAuth/AuthenticateUserTicket, for your app and the identity plany-encore |
| Opening, settling and reading an order | ISteamMicroTxn (or ISteamMicroTxnSandbox) |
| Refunds and chargebacks | ISteamMicroTxn/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.
"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.keysandboxis 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 inListPurchases. - 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
state | Meaning |
|---|---|
STATE_ACTIVE | The key works and owns at least one game. |
STATE_CREDENTIAL_INVALID | Steam 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.keyThree rules:
- The new key is checked the way the first one was, and its listings replace the old ones.
- 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. - 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.
The line of credit on the link
| Field | What it is |
|---|---|
outstanding | Credit Plany has issued to your projects through this link and you have not yet settled. Refunds reduce it. |
reserved | Credit held for purchases players have started and not finished. Counted against the limit, so two players cannot both take the last of it. |
outstanding_limit | The most outstanding + reserved may reach. Set by Plany, and $0 until it is. |
distributor_share_basis_points | Steam'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 steamSee Where the money goes.
Removing a link
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.
| Role | Links |
|---|---|
roles/account.owner | Everything. |
roles/account.billing | Create, read, rotate, remove. |
roles/account.admin | Read only. |
roles/account.viewer | Read only. |