Concepts
Security model
Who can do what in GameCoin, why a browser can never add coins to a balance, and what the service refuses by design.
On this page
The rule
A client never credits. Code that runs in a browser or on a phone can be read and changed by the player. So GameCoin never lets it add to a balance, give an item, correct a balance or refund an order. The browser can only make a player's own balance go down, or pay. One exception, by design: a player can redeem a gift code your studio created. The value comes from the code, not from the client: it gives free coins only, works once per player, has a limited number of uses, and every refusal looks the same so codes cannot be guessed (see Codes API).
That is what makes a game without a backend safe for real money. It also tells you where to put your own rules: whatever decides that a player earns something must run on your server.
What each holder can do
| Holder | Can | Cannot |
|---|---|---|
Secret key (gc_sk_…) | The whole server API for its game and environment: declare players, grant and spend, give and consume items, create checkouts, issue tokens, read and refund orders | Reach another game or the other environment |
Publishable key (gc_pk_…) | Read the catalog. Create an anonymous player, if the game allows it. | Anything on a player, without a token |
Publishable key + player token (gc_pt_…) | As that one player: read their wallet and inventory, spend, buy an item with a currency, consume an item, pay for a pack, read their own orders | Grant coins, give items, correct a balance, refund, act for another player |
| Dashboard session | What your role in the studio allows |
Behind each row, GameCoin checks four things on every request:
- The key says which game and which environment. Nothing in the request can change that.
- A player token names one player. A token cannot read the order of another player: it answers
404 NOT_FOUND. - Only a secret key reaches the server API, and only a publishable key reaches the client API. The wrong kind answers
403 FORBIDDEN. - A body with a field GameCoin does not know is refused. There is no hidden field that gives more power.
Why the client cannot credit
Think about a game where the browser could call grant. A player opens the developer tools, calls it with amount: 1000000, and owns a fortune. If the same game sells currency for money, that fortune is worth money.
With GameCoin, coins enter a balance in only two ways:
- a paid order, which GameCoin delivers after a payment;
- a call from your server with your secret key.
A player can change what their own browser does, but not what your server decides.
Reward on your server
A game with a server rewards players like this:
- The browser tells your server that something happened: "I finished level 3".
- Your server checks that it is true, using what it knows.
- Your server calls
grantwith an idempotency key built from the event.
The browser never says how much to credit. Your server does.
A game without a server cannot grant coins. It can still keep points of its own (a high score, experience, a progress bar) in the browser, and let players spend GameCoin currency on things. Do not use GameCoin currency as a prize that the browser decides to give out.
What GameCoin will not do
GameCoin keeps its currencies closed. It has no call for any of these, and none will be added:
| It will not | In plain words |
|---|---|
| Turn a currency back into money | Gems can be bought. They cannot be cashed out. Coins and items are for use inside your game. |
| Move a currency between players | There is no transfer, gift or trade of balances. Only your server can give coins to a player. |
| Share a currency between studios | A currency belongs to one game of one studio. |
| Take a bet or an entry stake | No wagering and no stake tournaments, where players pay in to win a prize. |
| Sell loot boxes for money | A pack states what it contains. A pack is not a mystery box. |
These limits keep a GameCoin currency a game token and not money. Design your economy within them.
How the API protects you
| Protection | How |
|---|---|
| Scope | The key picks game and environment; a resource of another game answers 404, never 403, so nothing about it is revealed |
| Strict bodies | An unknown field is a 400; a body is at most 64 KiB |
| Safe retries | Every write that changes a wallet or an inventory needs an idempotency key |
| No double spend | Operations on one wallet run one at a time |
| Return URLs | The successUrl and cancelUrl of a browser checkout must have the origin of the page that asks, so a script on another site cannot send your players somewhere else |
| CORS | Only the client API answers cross-origin requests, and only to the origins you allow for the game, so a secret key cannot be used from a web page by accident |
| Rate limits | Per key, per player and per IP: see Rate limits |
| Short tokens | A player token lasts one hour, since it cannot be revoked. Blocking the player stops it anyway. |
| Card data | Payment happens on a hosted page. No card number passes through your game or your server. |
Checklist before you ship
- The secret key is only on your server, read from the environment, and not in your repository or your game bundle.
- Your server decides every grant, and every grant has an idempotency key made from the event.
- Your token endpoint sits behind your own login, so a player can only get a token for themselves.
- The browser code uses the publishable key only.
- Your game handles
INSUFFICIENT_FUNDS,LIMIT_REACHEDandUNAUTHENTICATEDwithout crashing. See Errors. - You tried the whole flow in the test environment.
Where next
- Keys and environments
- A game with a backend: the flow that follows this model.