Gammon Stand API

Back

This is the API games use to talk to the arcade, to do things like accept tokens and get user info.

Coin acceptance API

Coins/tokens are also referred to as payments here.

There are no actual coins/tokens - everything is done via NFC cards, but anyway this API serves the general purpose of "accepting coins".

---
title: Singleplayer
---
flowchart TD
    ask_payment -->|Got payment| commit_payment[Send commit_payment]
    ask_payment --> wait_payment[Waiting for payment]
    wait_payment -->|Sleep 0.1s| ask_payment
    commit_payment --> start_game{Start game}
    
---
title: Multiplayer
---
flowchart TD
    player_select{No players} -->|Press start| ask_payment[Send ask_payment]
    ask_payment -->|Got payment| countdown
    ask_payment --> wait_payment[Waiting for payment]
    wait_payment -->|Sleep 0.1s| ask_payment
    wait_payment -->|Press start| player_select
    countdown -->|Countdown done| commit_payment[Send commit_payment]
    countdown[Start countdown] -->|Press start| release_payment[Send release_payment]
    release_payment --> player_select
    commit_payment --> start_game{Start game}

{"v1": { "ask_payment": { ... } } }

This does several things:

  1. Makes the card reader start accepting tokens, if it isn't already

  2. If no token has been accepted, returns an empty response

  3. If a token has been accepted, reserves that token (so future calls don't return the same token) and

  4. Returns the reservation ID

You're expected to repeatedly call this method (several times a second is fine) as long as you need a token, until you receive a token.

The first time you call this method it'll likely return no payment (token), just initialize the card reader.

If this method isn't called for a few seconds it stops accepting tokens.

Request structure

{ "v1": { "ask_payment": {
    "client_payment_id": {
      "game_id": "my_game",
      "id": "payment123"
    }
} } }

client_payment_id is a unique ID for the payment (an idempotency token) composed of your game ID and a unique portion you generate as you see fit. Basically, after a payment is made for a client_payment_id, all requests for that client_payment_id will return the same data and no further tokens will be accepted. Use different client_payment_ids to accept multiple coins. You can use a random number or the current timestamp if you don't need this functionality.

A committed payment will be recorded to the game in the client_payment_id.

Only one token can be requested at a time (there's only one reader). Making requests with a different client_payment_ids before a token is accepted will replace the previous request.

Success response, no token

{ "ok": {
    "payment": null
} }
    

Success response, token reserved

{ "ok": {
    "payment": {
        "client_payment_id": {
          "game_id": "my_game",
          "id": "payment123"
        }
    }
} }
    

id is the reservation ID, used by other calls.

{"v1": { "release_payment": { ... } } }

This releases a payment reservation. For instance, if a player that tapped in used the wrong card, or they decide they don't want to play before the game starts. This functionality is optional but may make for a better player experience.

Request structure

{ "v1": { "release_payment": {
    "client_payment_id": {
      "game_id": "my_game",
      "id": "payment123"
    }
} } }

Success response

{ "ok": null }
    

{"v1": { "commit_clear_payments": { ... } } }

When player selection is complete and no further changes can be made, call this to record the payment to the game. If any token reservations were lost (e.g. due to bugs), this call will also release them, and can be used to clear all reservations by sending the request with no "commit" reservations listed.

Request structure

{ "v1": { "commit_clear_payments": {
    "commit_payment_ids": [
        {
          "game_id": "my_game",
          "id": "payment123"
        }
    ]
} } }

Success response

{ "ok": null }