Partner platform model
Luckotto is one self-contained app: business pages, partner APIs, an embeddable player UI, and background scanner jobs.
Entity model
Lifecycle
- A website user creates a partner site and receives the initial API key.
- The user copies an /embed URL with partner ID, playerUname, and playerIdentifier.
- The embed queries /api/luckotto routes in the same monolith. Browser code never touches Postgres directly.
- The API routes quote and create Luckotto tickets from partner ID, player context, and requested numbers. Trusted server-side clients use /api/luckotto/orders/authenticated with the partner API key.
- The player sends Bitcoin to the order-specific deposit address.
- The root worker loop or scanner commands record payments, allocate non-overlapping Luckotto tickets, and settle rounds.
- Public round and Luckotto order pages remain visible on the website.
- An order record is public: anyone with its UUIDv7 can view its request, allocation, price, fee, and status.
Product rules
Single deploymentThe website, /api/luckotto routes, /embed player UI, and worker loop are built from one root package.
Database accessServer-side pages, route handlers, and jobs use shared root utilities to talk directly to Postgres.
API surfaceThe monolith exposes a small JSON REST surface under /api/luckotto.
Embed isolationThe embed communicates only with public /api/luckotto routes and can be embedded by partners.
No iframe secretsEvery API endpoint used by the iframe is public and must work without a partner API key.
Player contextPartners pass playerUname and playerIdentifier to create address hints and look up player Luckotto tickets.
REST APIPartner-facing API operations are plain JSON REST endpoints.
Iframe contract
FAQ<iframe title="Partner Lotto" src="https://luckotto.example/embed?partnerId=018f58d2-2802-7000-8000-000000000002&playerUname=DisplayName&playerIdentifier=opaque-public-id" style="width:100%;max-width:560px;height:760px;border:0;" loading="lazy" ></iframe>
The iframe URL carries public player context only. It must never include an API key or partner-owned pricing settings.