Architecture

Partner platform model

Luckotto is one self-contained app: business pages, partner APIs, an embeddable player UI, and background scanner jobs.

Entity model

EntityUserA website account that owns partner sites and manages API keys.
EntityPartner siteA B2B tenant addressed by UUID with display metadata, payout address, verification status, and one active server-side API key.
EntityAPI keyA single static partner secret for trusted server-side calls to /api/luckotto/orders/authenticated. It is never placed in iframe URLs or browser code.
EntityplayerUnameA public display name shown in public ledgers when supplied by a partner.
EntityplayerIdentifierA public opaque player identifier that can be shown anywhere but should be meaningless outside the partner system.
EntityLuckotto orderA quoted request for 6-25 numbers with a dedicated Bitcoin address, payment totals, allocation, and fee fields.
EntityDeposit addressA UUIDv7 record with a hash-tweaked Bitcoin address linked one-to-one to a Luckotto order.
EntityPaymentAn observed Bitcoin output to a deposit address.
EntityAllocated numbersThe actual same-size non-overlapping number set assigned after payment confirmation.
EntityRoundThe global Luckotto draw window shared by all partners.

Lifecycle

  1. A website user creates a partner site and receives the initial API key.
  2. The user copies an /embed URL with partner ID, playerUname, and playerIdentifier.
  3. The embed queries /api/luckotto routes in the same monolith. Browser code never touches Postgres directly.
  4. 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.
  5. The player sends Bitcoin to the order-specific deposit address.
  6. The root worker loop or scanner commands record payments, allocate non-overlapping Luckotto tickets, and settle rounds.
  7. Public round and Luckotto order pages remain visible on the website.
  8. 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.