Compliance & RTP
KINGSTONE provides built-in compliance tools for monitoring Return-to-Player (RTP) accuracy and generating audit evidence. As a partner, you can track RTP for every game, verify audit chains, and download compliance certificates.
How RTP Compliance Works
Every game has a certified RTP defined by its PAR sheet (for example, 92.5%). KINGSTONE pre-computes outcome queues that match this certified RTP. After outcomes are served to players, the actual RTP is calculated from real play data.
KINGSTONE compares actual RTP against certified RTP using a 2% tolerance. If the actual RTP is within 2 percentage points of the certified value, the game is marked as compliant.
| Certified RTP | Actual RTP | Variance | Status |
|---|---|---|---|
| 92.50% | 92.48% | -0.02% | Compliant |
| 92.50% | 91.80% | -0.70% | Compliant |
| 92.50% | 89.50% | -3.00% | Non-compliant |
Per-Game RTP Tracking
Get detailed RTP data for a specific game:
import { KingstoneClient } from '@kingstone/sdk';
const client = new KingstoneClient({
apiKey: 'ks_sandbox_your_key_here',
sandbox: true,
});
const rtp = await client.getRtpCompliance(1); // gameId
console.log(`Game: ${rtp.displayName} (${rtp.configName})`);
console.log(`Certified RTP: ${(rtp.certifiedRtp * 100).toFixed(2)}%`);
console.log(`Actual RTP: ${rtp.latestActualRtp !== null ? (rtp.latestActualRtp * 100).toFixed(2) + '%' : 'No data yet'}`);
console.log(`Variance: ${rtp.latestVariance !== null ? (rtp.latestVariance * 100).toFixed(4) + '%' : 'N/A'}`);
console.log(`Compliant: ${rtp.isCompliant ? 'Yes' : 'NO'}`);
console.log(`Total plays: ${rtp.totalPlays}`);
console.log(`Total blocks: ${rtp.totalBlocks}`);The response also includes a blocks array with per-block RTP history:
for (const block of rtp.blocks) {
console.log(` Block ${block.blockSequenceNumber}: RTP ${(block.rtpActual * 100).toFixed(2)}% (variance ${(block.rtpVariance * 100).toFixed(4)}%) — ${block.blockStatus}`);
}Compliance Summary
Get a high-level overview of all your games:
const summary = await client.getComplianceSummary();
console.log(`Total games: ${summary.totalGames}`);
console.log(`Compliant: ${summary.compliantGames}/${summary.totalGames}`);
for (const game of summary.games) {
const status = game.isCompliant ? 'OK' : 'ALERT';
const actualStr = game.latestActualRtp !== null
? (game.latestActualRtp * 100).toFixed(2) + '%'
: 'No data';
console.log(` [${status}] ${game.displayName}: certified ${(game.certifiedRtp * 100).toFixed(2)}%, actual ${actualStr}`);
}Compliance Certificates
For regulatory submissions, you can generate a compliance certificate for any game. The certificate includes all RTP data, block history, and a deterministic certificate ID.
const cert = await client.getComplianceCertificate(1); // gameId
console.log(`Certificate ID: ${cert.certificateId}`);
console.log(`Issued: ${cert.issuedAt}`);
console.log(`Issuer: ${cert.issuer}`);
console.log(`Game: ${cert.displayName}`);
console.log(`Certified RTP: ${(cert.certifiedRtp * 100).toFixed(2)}%`);
console.log(`Actual RTP: ${cert.actualRtp !== null ? (cert.actualRtp * 100).toFixed(2) + '%' : 'No data'}`);
console.log(`Compliant: ${cert.isCompliant}`);
console.log(`Tolerance: ${cert.rtpTolerancePercent}%`);
console.log(`Blocks analyzed: ${cert.totalBlocksAnalyzed}`);
console.log(`Total plays: ${cert.totalPlays}`);The certificate ID is deterministic — the same game at the same point in time always produces the same certificate ID. This makes it suitable for regulatory record-keeping.
Audit Trail Verification
Every spin creates a SHA-256 hash-chained audit record. You can verify the integrity of the entire chain to confirm that no records have been modified or deleted.
const verification = await client.verifyAuditChain(1); // gameId
console.log(`Chain valid: ${verification.isValid}`);
console.log(`Sessions verified: ${verification.sessionsVerified}`);
console.log(`Broken links: ${verification.brokenLinks.length}`);
if (!verification.isValid) {
console.log(`Broken at indices: ${verification.brokenLinks.join(', ')}`);
}You can also retrieve the raw audit log for your own analysis:
const { sessions } = await client.getAuditLog({
gameConfigId: 1,
page: 1,
limit: 50,
});
for (const session of sessions) {
console.log(` Session ${session.sessionId}: SPP ${session.sppValue}, tier T${session.prizeTierId}, payout $${session.payoutUsd.toFixed(2)}`);
console.log(` Hash: ${session.auditHash.slice(0, 16)}...`);
}Why This Matters for Partners
- Regulatory submissions — Use compliance certificates and audit verification to demonstrate mathematical fairness to regulators.
- Player trust — The deterministic, auditable system proves that outcomes are not manipulated.
- Dispute resolution — If a player disputes an outcome, the audit trail provides complete evidence of what happened and why.
- Continuous monitoring — Track RTP drift in real time and catch anomalies early.
Next Steps
- Review the full Error Codes reference for compliance-related errors
- Set up
settlement.report_readywebhooks for automated reconciliation
