Skip to content
Skip the menu

API reference

Orders API

Follow an order from payment to delivery, and refund a paid order to take its coins and items back, with the server API.

View as Markdown

On this page

An order is the purchase of a pack with real money, created by a checkout. It moves through a few statuses, from pending when the player has not paid yet to fulfilled once the coins and items are delivered. This page reads an order and refunds it. The examples on this page continue from the setup, and use the id of an order that the player has paid.

Get an order

Returns an order with its current status. Use it when the player comes back from the payment page, to confirm that the coins were delivered before you tell them, and to follow an order you created.

GET/orders/{orderId}

Authentication: secret key. Idempotency: not needed.

Path parameters

ParameterTypeDescription
orderIdstringThe id of the order: 24 hexadecimal characters, as returned by Order a currency pack.
LangageLanguage
curl "https://gamecoin.apilow.com/api/v1/orders/665f1c2e8a3b4d5e6f7081b4" \
  -H "Authorization: Bearer $GAMECOIN_SECRET_KEY"

Response 200 OK: an Order. The one below was created by a checkout and paid in the simulated payment page.

JSON
{
  "id": "665f1c2e8a3b4d5e6f7081b4",
  "playerId": "665f1c2e8a3b4d5e6f708192",
  "status": "fulfilled",
  "pack": { "sku": "gems-500", "name": "Bag of gems" },
  "amountCents": 499,
  "currency": "EUR",
  "country": "BE",
  "vatRateBp": 2100,
  "vatCents": 87,
  "netCents": 412,
  "createdAt": "2026-10-05T22:14:32.995Z",
  "paidAt": "2026-10-05T22:14:34.054Z",
  "fulfilledAt": "2026-10-05T22:14:34.054Z",
  "refundedAt": null,
  "creatorCode": null
}

Errors

StatusCodeWhenWhat to do
404NOT_FOUNDNo order has this id in your game and environment (including an id that is not 24 hexadecimal characters)Check the id, and that the key is the one of the game that created the order.
JSON
{ "error": { "code": "NOT_FOUND", "message": "Order not found" } }

Notes

  • The status is the truth. Never rely on the ?status= of the return URL: read the order.
  • A new order is pending. When the payment succeeds it goes to fulfilled within moments: the coins and items are delivered, paidAt and fulfilledAt are set. paid is a short step on the way, so you will rarely see it. If the player has not paid yet, poll the order every few seconds, or read it when they come back.
  • The final statuses are fulfilled (until a refund), refunded, chargeback, failed (the payment was refused), canceled and expired (a pending order that was not paid within one hour). They are described in Objects.
  • amountCents is the price in euro cents, VAT included; vatRateBp is the rate in basis points (2100 is 21 %); vatCents and netCents split the amount.
  • An order is only visible with the key of the game that created it. The browser reads its own orders with Get an order of the token player.

Refund an order

Refunds a paid order: the money goes back to the player, and the coins and items the order delivered are taken back. Use it when a player asks for their money back, or when you cancel a sale.

POST/orders/{orderId}/refund

Authentication: secret key. Idempotency: none: this call has no Idempotency-Key. Do not blindly retry it: see the notes.

Path parameters

ParameterTypeDescription
orderIdstringThe id of a fulfilled order: 24 hexadecimal characters.

Body (JSON; optional, an empty body means {})

FieldTypeRequiredRules
reasonstringnoFree text, at most 500 characters, recorded with the refund.
LangageLanguage
curl -X POST "https://gamecoin.apilow.com/api/v1/orders/665f1c2e8a3b4d5e6f7081b4/refund" \
  -H "Authorization: Bearer $GAMECOIN_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"reason": "Player request"}'

Response 200 OK: the Order, now refunded, with refundedAt set.

JSON
{
  "id": "665f1c2e8a3b4d5e6f7081b4",
  "playerId": "665f1c2e8a3b4d5e6f708192",
  "status": "refunded",
  "pack": { "sku": "gems-500", "name": "Bag of gems" },
  "amountCents": 499,
  "currency": "EUR",
  "country": "BE",
  "vatRateBp": 2100,
  "vatCents": 87,
  "netCents": 412,
  "createdAt": "2026-10-05T22:14:32.995Z",
  "paidAt": "2026-10-05T22:14:34.054Z",
  "fulfilledAt": "2026-10-05T22:14:34.054Z",
  "refundedAt": "2026-10-05T22:14:40.586Z",
  "creatorCode": null
}

Errors

StatusCodeWhenWhat to do
400VALIDATION_FAILEDAn unknown field, or a reason longer than 500 charactersRead details.fieldErrors.
402PAYMENT_FAILEDThe payment provider could not refundRetry later; the order is unchanged.
404NOT_FOUNDNo order has this id in your game and environmentCheck the id.
409CONFLICTThe order is not fulfilled: it is pending, failed, expired, already refunded… (details.from is its status)Nothing to refund. Read the order to see where it stands.
JSON
{
  "error": {
    "code": "CONFLICT",
    "message": "Order cannot go from pending to refunded",
    "details": { "from": "pending", "to": "refunded" }
  }
}

Notes

  • Only a fulfilled order can be refunded, and only once. The money is refunded to the player; in the test environment the refund is simulated.
  • The coins are taken back with a ledger entry of type refund_clawback that points to the order: the paid and bonus amounts that the pack delivered. The items of the pack are removed from the inventory, up to what the player still owns.
  • If the player has already spent the coins, the balance goes below zero: the shortfall is kept as a debt on the paid part, and the next credits repay it first. A game setting (« Après un remboursement » in the dashboard, which is in French for now) can stop balances at zero instead. A player in debt cannot spend until the debt is repaid.
  • A refund has no idempotency key. After a network error or a 5xx, do not retry blindly: read the order with Get an order. If it is refunded, the refund went through; a second refund would answer CONFLICT anyway. The SDKs retry a refund on 429 only.
  • A pack with maxPerPlayer can be bought again after a refund: a refunded order does not count toward the limit.