Delivered remotely for a business based in Prague, Czech Republic. Names withheld by agreement.
Project Overview
Industry: Sports gaming — real-money prediction contests.
Type of solution: A REST API and administrative platform with a cross-platform mobile application and a progressive web app, integrated with a live sports odds provider.
Business context: Paid prediction contests look like a consumer product and behave like a financial one. Every entry moves money, every result determines a payout, and every payout has to be defensible if questioned. Add a regulated environment where who may participate depends on where they are, and the engineering priorities shift decisively: correctness, auditability and controlled money movement matter more than feature breadth.
General users: Players who fund an account, enter competitions and withdraw winnings; and the operator's administrative and finance team, who create competitions, enter results, settle contests and approve payouts.
General purpose: To run paid sports prediction contests with live market data, multiple contest formats, an auditable money trail and the operational controls a money-handling product requires.
The Business Challenge
Contests need live market data. A prediction contest that does not reflect real events and real market prices is not credible. That means integrating a live odds feed and handling its rate limits, latency and availability as a permanent operating condition rather than an integration task.
Prices move between display and commitment. The odds a user sees when they open a screen are not necessarily the odds a minute later. If the platform settles against a live value rather than the value the user actually accepted, settlement becomes indefensible — and in this domain, indefensible means disputed.
One format is not enough. Pooled competitions with prize structures and direct head-to-head matchups are different products with different settlement logic, but they need to share entry, payment, results and payout infrastructure.
Money has to reconcile. Entry fees in, winnings out, deposits, withdrawals and promotional credit all have to add up, with every movement traceable. A consumer app can tolerate an ambiguous state; a money-handling platform cannot.
Payouts need control. Withdrawals cannot be automatic. They require review, an approval decision, a rejection path with a recorded reason, and protection against being processed twice.
Eligibility is a regulatory obligation. Who may participate depends on jurisdiction. This is not a preference setting — it is a condition of operating.
Settlement is the highest-consequence code in the product. Results determine money movement. An error here is not a bug report; it is a financial loss and a credibility problem.
Time governs everything. Competitions open, lock and settle against a clock tied to real-world events, and the interface must always show the true current phase.
Our Approach
Capture the price at the moment of commitment. The foundational decision was that a selection stores the odds, price and timestamp as they stood when the user committed — not a reference to a value that will keep moving. Settlement is then computed against exactly what the user was shown. Everything else in the product depends on this being right.
Persist market history rather than overwriting it. Odds movement is stored as history, giving both an audit trail and the underlying data for analysis and dispute resolution.
Snapshot upstream fixture data. The relevant payload from the odds provider is stored with the competition, so settlement does not depend on a third-party API still returning that fixture days later. The platform's obligations outlive the provider's response cache.
Build money movement as a ledger, not as a balance. Every movement — entry fee, winnings, deposit, withdrawal, promotional credit — is a typed transaction record carrying its amount, external reference, status and, where applicable, the full raw provider payload. A balance is derived from history rather than being the only thing recorded.
Gate payouts through people. Withdrawal requests enter an approval workflow with explicit accept and reject outcomes, and a recorded reason on rejection so the decision can be explained to the user and reviewed later.
Treat administration as a core product. Competition creation, results entry, settlement, withdrawal approval, promotional codes, jurisdiction management, content and user administration were built as a full operational platform, because in this domain the operator's daily work is as central as the player experience.
Reach players on more than one surface. A cross-platform mobile application covers both mobile platforms from one codebase, with a progressive web app extending reach without a third build.
The Solution
Competition catalogue. Competitions carry their format, entry fee, pool size, prize structure, top prize, how-to-play content, rules, and start and lock times, with status governing their lifecycle. Players see what a contest costs, what it pays and how it works before entering.
Multiple contest formats. Pooled competitions with prize structures run alongside direct head-to-head matchups, where an entry is paired against a specific opponent with both sides' stakes, points, placing and winnings recorded on the same record.
Live odds integration. Market data is retrieved from a commercial sports odds provider, populating competitions with real fixtures and real prices, with the market history retained.
Lock-time selection capture. When a player makes a selection, the platform records the teams, the chosen side, the stake, the selection type and — critically — the odds, price and exact time at which the selection locked.
Entry and stake management. Entering a competition creates a record carrying the entry fee and credit committed, joined to the player and the competition, with head-to-head entries carrying the opponent's parallel figures.
Results and settlement. Administrators enter results, and the platform records points, placing and winnings per entry, driving the corresponding credit movements.
Transaction ledger. Every money movement is a typed transaction with amount, timestamp, external reference, raw provider payload, status and — where relevant — a rejection reason, giving finance a complete, reconcilable history.
Withdrawal workflow. Players request withdrawals; administrators approve or reject with a recorded reason; the ledger reflects the outcome. Payouts are a controlled operational process rather than an automatic transfer.
Promotional codes. Promo codes with usage tracking support acquisition and retention campaigns without ad hoc credit adjustments.
Jurisdiction eligibility. Players are associated with a jurisdiction, and jurisdiction data is administratively managed, so participation rules can be applied and updated as the regulatory picture changes.
Community and content. Comments on competitions, plus administratively managed content pages, FAQs, rules and general messages, so player-facing information can be maintained without a release.
Notifications. Push notification delivery with a device token registry, including targeted administrative dispatch for time-sensitive announcements.
Multi-surface delivery. A cross-platform mobile app for both platforms, plus a progressive web app for players who prefer the browser.
Key Features
Lock-time odds and price capture Selections record the exact odds, price and timestamp at commitment, so settlement is computed against what the player actually accepted rather than a value that has since moved.
Persistent odds history Market movement is stored rather than overwritten, providing an audit trail for dispute resolution and a dataset for analysis.
Pooled and head-to-head contest formats Prize-pool competitions and direct one-against-one matchups share entry, payment and settlement infrastructure while supporting different competitive experiences.
Full transaction ledger Typed transaction records for every money movement, retaining external references and raw provider payloads for reconciliation.
Approval-gated withdrawals Payout requests pass through explicit approval or rejection, with recorded reasons — a controlled operational process rather than an automatic transfer.
Upstream fixture snapshotting Relevant provider data is stored with the competition, so settlement is not dependent on a third-party API's continued availability of historical fixtures.
Jurisdiction eligibility management Player jurisdiction association with administratively managed jurisdiction data, supporting participation rules that change with the regulatory environment.
Promotional code system Codes with usage tracking, enabling campaigns without manual credit adjustments that would compromise the ledger.
Complete operational back office Competition management, results entry and settlement, withdrawal approval, user administration, content management, spreadsheet export and targeted notifications.
Multi-surface player access A single cross-platform mobile codebase covering both platforms, extended by a progressive web app for browser-based play.
Technical Architecture
Player clients. A cross-platform mobile application using a predictable state container with asynchronous middleware, navigation composed from stack, tab, drawer and swipeable top-tab navigators to support multi-format contest browsing, and a Material component library for consistent presentation. A progressive web app provides browser access from the same platform.
API layer. A token-authenticated JSON API serving both player surfaces, with cross-origin controls and a controller tree kept separate from administrative code.
Administrative platform. A server-rendered back office with server-side processed data grids covering competitions, results, settlement, withdrawals, users, promotions, jurisdictions and content.
Application layer. Controllers partitioned by audience over shared base classes and a global helper module, with domain models covering competitions, entries, selections, odds history, transactions, withdrawals and supporting reference data.
Integration layer. Outbound HTTP integration with a commercial sports odds provider, retrieving fixtures and market prices, persisting odds history and snapshotting fixture payloads onto competition records.
Data layer. A relational database with soft deletion throughout — appropriate in a domain where destroying a settled record is indefensible — and model-level query caching applied to frequently read catalogue data.
Supporting services. Cloud object storage for media, transactional email through dedicated delivery providers, image processing, spreadsheet export and push notification delivery.
Flow: Mobile app / PWA → Token-authenticated API → Contest, entry and selection logic → Relational database (ledger, odds history, entries) → Odds provider integration → Administrative settlement → Transaction ledger → Withdrawal approval → Notifications
Technology Stack
| Category | Technology |
|---|---|
| Backend language | PHP |
| Backend framework | Laravel |
| Database | MySQL with Doctrine DBAL, soft deletes throughout |
| API authentication | Laravel Passport (OAuth2) and Sanctum |
| Query caching | Model-level caching layer |
| Administrative grids | Yajra DataTables (server-side processing) |
| External data | Commercial sports odds API via HTTP client |
| Object storage | Google Cloud Storage |
| Email delivery | SendGrid and Postmark |
| Image processing | Intervention Image |
| Spreadsheet export | Maatwebsite Excel |
| Web delivery | Progressive Web App support |
| Diagnostics | Log viewer packages |
| Mobile framework | React Native |
| Mobile state | Redux with Thunk middleware |
| Mobile navigation | React Navigation (stack, bottom tabs, drawer, material top tabs) |
| Mobile UI | React Native Paper, tab and pager views |
| Mobile networking | Axios |
| Device capabilities | Connectivity detection, geolocation, date/time pickers, masked input |
Technical Challenges & Solutions
| Challenge | Our Approach |
|---|---|
| Market prices move between what a player sees and what they commit to | Selections capture the odds, price and exact timestamp at lock, so settlement computes against the value the player actually accepted — the foundational correctness decision in a wagering product. |
| Settlement depending on a third-party API days after the event | The relevant fixture payload is snapshotted onto the competition record and odds movement is persisted as history, so the platform can settle from its own data regardless of provider availability. |
| Two contest formats with different settlement logic | Pooled and head-to-head play share entry, payment and results infrastructure, with the head-to-head case carrying the opponent's parallel stake, points, placing and winnings on the same record so one settlement path serves both. |
| Money that must reconcile and be explainable | A typed transaction ledger recording every movement with amount, external reference, raw provider payload and status, so balances are derived from an auditable history rather than being the only record kept. |
| Payouts that must not be automatic or repeatable | Withdrawal requests routed through explicit administrative approval or rejection, with a recorded reason on refusal, making payout decisions controlled, explainable and reviewable. |
| Participation eligibility as a regulatory condition | Jurisdiction association held on the player record with administratively managed jurisdiction data, so eligibility rules can be applied and updated as the regulatory position changes without code deployment. |
| Deleting records in a domain where history must survive | Soft deletion applied throughout, so records can be withdrawn from active use while the settled history that references them remains intact. |
| Repeated reads on catalogue data under load | Model-level query caching applied to entities that change infrequently, reducing database pressure on the paths players hit most. |
| Reaching players on both mobile platforms and the web | One cross-platform mobile codebase serving both platforms, extended by a progressive web app rather than a third native build. |
Security & Reliability
Authentication. Token-based OAuth2 authentication for API access, with email verification and password recovery flows.
Surface separation. Player-facing API endpoints and administrative functionality live in separate controller trees, so operational capability is not reachable from the player surface.
Cross-origin controls. Explicit policy governing which clients may call the API.
Eligibility gating. Jurisdiction association on the player record supports participation rules required by the operating environment.
Money-movement integrity. Every financial event is recorded as a typed ledger entry retaining external references and raw provider responses, so reconciliation and dispute investigation work from source data.
Controlled payouts. Withdrawals require explicit administrative approval, with rejection reasons recorded, preventing automatic outflow and creating an audit trail for every decision.
Non-destructive data handling. Soft deletion throughout preserves the historical record underpinning settled contests.
Operational visibility. Administrative dashboards, spreadsheet export and log inspection tooling give the operator insight into platform activity and the ability to investigate individual cases.
Scalability & Performance
Model-level caching. Frequently read catalogue data is cached at the model layer, reducing repeated database reads on the highest-traffic player paths.
Server-side administrative grids. Administrative listings page, sort and filter at the database level, so operational screens remain usable as contest and transaction history accumulates.
Snapshotted external data. Storing fixture payloads with competitions removes an external API call from read paths, improving both latency and resilience.
Stateless API tier. Token authentication and cloud object storage keep application instances free of local state, supporting horizontal scaling.
Efficient media handling. Image processing through a dedicated library with storage in cloud object storage rather than on application servers.
Single mobile codebase. One cross-platform application plus a progressive web app covers three surfaces without triplicating engineering effort.
Business Outcomes
- Settlement is defensible, because every selection records the price and time the player actually committed to.
- Contests reflect real markets, through live odds integration with retained market history.
- The platform supports more than one competitive format, with pooled and head-to-head play over shared infrastructure.
- Money reconciles, through a typed ledger that records every movement with its external reference and raw provider response.
- Payouts stay under operator control, with explicit approval, recorded rejection reasons and a reviewable trail.
- Eligibility rules can change without a release, because jurisdiction data is administratively managed.
- The operations team can run the business, with settlement, withdrawal approval, promotions, content and user administration built as a complete back office.
- Players are reached on three surfaces — two mobile platforms and the web — from a single mobile codebase plus a progressive web app.
Why it worked
Money-handling platforms are unforgiving in a way that ordinary consumer software is not. An ambiguous state in a social app is a bug. An ambiguous state in a settlement path is a financial loss, a dispute, and a credibility problem that outlasts the fix.
Our team builds for that standard. We capture the values a decision was made against rather than referencing values that keep moving. We record money as an auditable ledger rather than a mutable balance. We snapshot external data the business will still be accountable for after the provider has moved on. We gate outbound money through human approval with recorded reasons. And we treat the operator's back office as a first-class product, because in this category the operations team uses the software more intensively than any player does.
Our teams work across Laravel and modern PHP, OAuth2-secured API design, third-party data integration with real availability constraints, cross-platform mobile development and progressive web delivery. Just as importantly, we understand which parts of a system like this deserve disproportionate care — and settlement, ledgers and payouts are always at the top of that list.
Final Summary
A paid prediction contest platform presents itself as a consumer app and behaves like a financial system. Every entry commits money, every result triggers a payout, and every payout must be explainable if a player disputes it. Layer on a regulated environment where eligibility depends on jurisdiction, and the engineering priorities become unambiguous: correctness, auditability and controlled money movement come before everything else.
Our team built a platform on those priorities. Live market data from a commercial odds provider populates real contests, and — the decision everything else rests on — each selection captures the odds, price and timestamp at the moment the player commits, so settlement is computed against what they actually accepted. Market history is persisted rather than overwritten, and upstream fixture data is snapshotted onto the competition, so the platform can settle from its own records regardless of what a third-party API returns later. Pooled and head-to-head formats share one entry, payment and settlement path. Every money movement lands in a typed ledger retaining external references and raw payloads, and withdrawals pass through explicit administrative approval with recorded reasons.
Around that core sits a complete operational back office — competition management, settlement, payout approval, promotions, jurisdiction management, content and user administration — and player access across two mobile platforms and the web from a single cross-platform codebase plus a progressive web app. For any operator whose product moves real money against real-world events, this is the architecture that makes the business defensible rather than merely functional.