Challenge
Docs>Get started>Overview

Overview

Challenge lets a player pay a fee to attempt a fixed standard in your game, and pays them a fixed prize when they beat it.

Challenge funds the prize, announces it before the player pays, and never pools one player's fee into another player's winnings. There is no opponent, no wager and no pot. There is a bar, a fee to try it, and a prize for clearing it.

You add two script tags and one server handler. Challenge does the rest.

What you build, what Challenge runs

The integration has two halves and one hard line between them.

SideHoldsDoes
Your game, in the browserThe program ID, which is publicMounts Challenge.js, records ordinary rounds, starts paid rounds
Your serverThe secret key (sk_test_, sk_live_)Receives finished rounds and reports the measurement to /v1
ChallengeEverything elseAccounts, money, the bar, the verdict, every player-facing screen

Challenge runs all of the following, and none of it is yours to build:

  • Accounts, sign-in and single sign-on across games
  • Age and identity verification
  • Deposits, balances, withdrawals and the ledger behind them
  • Responsible gaming limits and self-exclusion
  • The arming flow, the fee confirmation and every result screen a player sees
  • Measuring a Challenge's bar from real rounds, then monitoring it for drift
  • Publishing the next rung when a player claims one, and pricing it
  • Funding and paying the prize

What you build is three calls in the browser and one HTTPS request from a server you control.

The integration at a glance

The browser half. Two script tags and one call, then one line at the end of every round, then one line to start a paid round.

<script src="https://api.withchallenge.com/widget/dist/island-stub.js"></script> <script async src="https://api.withchallenge.com/widget/dist/island.js"></script>
Challenge.init({ program: '<<YOUR_PROGRAM_ID>>' }) // At the end of every round, paid or free, signed in or not. Challenge.record('moves', 34) // When the player has armed a Challenge on the island and a paid round begins. const attempt = await Challenge.startAttempt() // { attemptId, feeCharged, prizeOffered, threshold, thresholdDirection }

The server half. One request, with your key, once the round is finished.

// The key lives on your server. It never reaches the browser. const settled = await fetch( `https://api.withchallenge.com/v1/attempts/${attemptId}/outcome`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-API-Key': process.env.CHALLENGE_API_KEY, 'Idempotency-Key': attemptId, }, body: JSON.stringify({ score: 34 }), } )

Nothing is relayed back to your game. Challenge applies the bar it froze onto the attempt, pays the prize if it was met, and the island renders the result on its own.

Three rules decide where money can be created, and every other part of the API follows from them: scores enter the money system only from an authenticated partner server, fees are charged before scores are heard, and the bar and the prize freeze at the start of the attempt. The trust model states each one and what it forbids.

Key vocabulary

TermMeaning
ProgramYour game, as Challenge knows it. The program ID is public and goes in the browser.
ChallengeThe product unit. One standard a player can attempt: a metric, a bar, a fee and a prize. Never called a challenge.
MetricWhat is measured, in your game's own units: moves, seconds, points.
The barThe threshold a score is judged against, and its direction. Measured from real rounds by Challenge, never chosen by hand, because a bar you picked would set the pass rate, which would set what Challenge expects to pay.
The islandThe Challenge surface that sits over your game. It shows what is on offer, takes the fee confirmation, and renders the result. It is Challenge's, not yours: you never draw a fee, a balance or a verdict.
AttemptOne paid try. Created with the fee charged and the bar frozen, settled by an outcome, expired and refunded if no outcome arrives within an hour.
ArmA player agreeing to a Challenge and its fee, on the island, by their own tap. There is no API to arm for them, because agreeing to a price is the player's act.
OutcomeThe score your server reports, plus Challenge's determination of whether it met the frozen bar.
AwardThe prize paid when it did.
CalibrationThe free period a new Challenge spends collecting rounds before it can charge.
RungA harder Challenge, worth twice the one below it, unlocked by claiming that one. Spawned and priced by Challenge.
Integrity tierThe prize ceiling and verification level for your program. It does not decide who reports a score.
Program keysk_test_ for sandbox, sk_live_ for production. Server side only, always.
player_refYour own identifier for a player, used when your server creates attempts through /v1.

The documentation set

Start with the Quickstart if you want a settled attempt in front of you within the hour. Read How a round works first if you want to understand the loop before you write any of it.

Get started

PageWhat it answers
OverviewWhat Challenge is, what you build versus what Challenge runs, where everything else is
QuickstartThe shortest path from an unmodified game to a settled attempt in sandbox
How a round worksThe full lifecycle of one paid round, as a sequence, actor by actor
The trust modelThe three rules, what each forbids, and what each means for your code

Concepts

PageWhat it answers
Programs and keysProgram ID versus sk_test_ and sk_live_, which surface each may touch, approval and rotation
ChallengesMetric, threshold, direction, fee, prize, and the status machine behind them
CalibrationHow a bar is measured, the three paths to one, the provisional cap and the prize ramp
The Challenge ladderRungs, claim to unlock, prize doubling, and where locked rungs are listed
TournamentsHouse-funded fixed purses, rounds, entry rules, minimum fill and rank settlement

Build

These pages are being written. Until they land, the Quickstart and the Challenge.js reference carry the browser half and the /v1 API reference carries the server half.

PageWhat it will answer
Install Challenge.jsThe two scripts, init({ program }), anchors, theme, SPA mount and destroy()
Record roundsChallenge.record(metric, score), why it ships before anything chargeable, limits, metric naming
Start a paid attemptArming, startAttempt(), the frozen fields it returns, branching on .code
Report the score from your serverPOST /v1/attempts/{id}/outcome, both server templates in full
Server-created attemptsPOST /v1/players and POST /v1/attempts, only for games with no browser client
WebhooksHandler, registration, signature verification, retries, debugging
Real-time settlementWhat Challenge.js already does, and when you need none of it

Test and go live

PageWhat it answers
SandboxTest keys, the money-free loop a calibrating Challenge gives you, sandbox versus production
Simulate a Challenge's lifeThe portal batch simulator, its controls, and a worked drift suspension
Go-live checklistApproval, key swap, ceilings, ramp, webhook verification, error branching

Reference

PageWhat it answers
Challenge.jsEvery option, method, error code and catalog element in the browser half
APIAll of /v1: authentication, decimal-string money, idempotency, the error contract
Webhook eventsEvery event with its payload, trigger condition and delivery semantics
ErrorsThe full catalog, grouped by surface, with cause and fix for each code

For AI coding agents

An agent integrating Challenge in one pass should fetch /integrate.md, which is self-contained and executable with no further fetches, and /llms.txt for the index and the standing instructions. Both are generated from these pages, so neither can drift from them.


Source: https://www.withchallenge.com/docs/overview.md Docs index for AI agents: https://www.withchallenge.com/llms.txt

Ready to integrate?

Put a Bounty in your game in minutes.

Challenge for Players

Create an account, deposit funds, and compete for real money in games you already play.

Challenge for Developers

Add Challenge to your game and start earning from every match. Integration takes minutes.