Server-to-Server Implementation Guide
This guide walks backend developers step by step with pseudocode through everything needed to integrate server-to-server endpoints.
1. Database Deposits Table
Create the deposits
table:
CREATE TABLE deposits (
deposit_id VARCHAR(36) PRIMARY KEY,
user_id VARCHAR(36) NOT NULL,
amount INTEGER NOT NULL,
result VARCHAR(36)
);
2. /thndr/pay
Endpoint
/thndr/pay
EndpointPayload:
{
"userId": "<userId>",
"depositId": "<depositId>",
"amount": 1234
}
Execute following commands in one SQL transaction:
Check if this deposit was already processed:
const deposits = sql("
SELECT * FROM deposits
WHERE deposit_id = body.depositId
");
if(deposits.length > 0) {
res.status(200).send('Already processed');
}
Debit the user
const results = sql("
UPDATE user_balances SET balance = balance - body.amount
WHERE user_id = body.userId
AND balance >= body.amount
");
if(results.length == 0) {
// Insufficient balance or user not found
res.status(400).send(
{
{
errors: [
{
code: 'INSUFFICIENT_BALANCE',
isClientSafe: true,
},
],
}
});
}
Store deposit for idempotency and future result:
sql("
INSERT INTO deposits(deposit_id, user_id, amount, result)
VALUES (body.depositId, body.userId, body.amount, NULL)
");
3. /thndr/results
Endpoint
/thndr/results
EndpointPayload:
{
"userId": "<userId>",
"depositId": "<depositId>",
"result": "WIN" | "DRAW" | "LOSE" | "REFUND",
"amount": 1234
}
Execute following commands in one SQL transaction:
Check if deposit exists
const deposits = sql("
SELECT * FROM deposits
WHERE deposit_id = body.depositId
");
if(deposits.length == 0) {
// Unknown deposit, ignoring
res.status(200).send('Deposit ignored');
}
Check if result already processed
const deposit = deposits[0];
if (deposit.result !== null) {
res.status(200).send('Result already processed');
}
Process the result:
if (body.result === 'WIN' ||
body.result === 'DRAW' ||
body.result === 'REFUND') {
// Credit the user
sql("
UPDATE user_balances
SET balance = balance + body.amount
WHERE user_id = body.userId
");
} else if (body.result === 'LOSE') {
// For result 'LOSE', no balance changes needed
}
Mark deposit as processed
sql("
UPDATE deposits
SET result = body.result
WHERE deposit_id = body.depositId
");
Last updated