Technical reference

REST API and database contract

Partner-facing access is a small JSON REST API inside the same Next app as first-party admin pages.

Iframe contract

<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 calls public /api/luckotto endpoints and must never receive an API key or partner-owned pricing settings.

API contracts

GET /api/luckotto/bootstrapReturns partner metadata, Luckotto constants, selected round, player tickets, public tickets, and partner fee rate.
GET /api/luckotto/roundsReturns public round history for a partner, including draw order on settled rounds.
POST /api/luckotto/orders/quoteReturns a suggested weighted claim budget and explicit partner fee for selected hint numbers.
POST /api/luckotto/ordersCreates a player number hint and returns a fresh Bitcoin deposit address.
GET /api/luckotto/orders/:idReturns one finalized public Luckotto ticket by UUID.
GET /api/luckotto/ordersReturns public player ticket history for a partner/player pair.
POST /api/luckotto/orders/authenticatedTrusted server-side hint creation using the partner API key.

Lifecycle

  1. Website user creates or rotates a partner API key.
  2. The embed calls /api/luckotto/bootstrap to load public display data.
  3. Iframe quotes selected hint numbers, creates a deposit address hint, and receives a Bitcoin address.
  4. Every confirmed payment to any old or new deposit address becomes eligible for ticket allocation.
  5. The scanner allocates the best non-overlapping candidate it finds within the payment amount.
  6. Round settlement stores the full weighted draw order and finds the first sold ticket to complete six hits.
  7. The monolith exposes public round, ticket, allocation, fee, and payout data.

Website page routes

Luckotto embed/embed
Both surfaces. Embeddable Luckotto player UI served by the monolith.
Luckotto website only/, /account, /admin, /admin/payments, /demo, /docs, /docs/faq, /docs/luckotto, /docs/platform, /docs/technical, /hash-tweak, /login, /ticket-calculator, /partners/new, /partners/:partnerId, /partners/:partnerId/demo, /verify
Luckotto website only. First-party Luckotto product, account, public partner profiles, partner dashboards, demos, documentation, and verification pages.
Shared public pages, website surface/rounds, /rounds/:roundNumber, /orders/:orderId
Both surfaces. Public round and Luckotto order records shown inside the normal Luckotto website chrome.

API routes

Shared data APIsGET /api/luckotto/bootstrap, /api/luckotto/orders, /api/luckotto/orders/:orderId, /api/luckotto/orders/authenticated, /api/luckotto/orders/quote, /api/luckotto/rounds, /api/rounds, /api/rounds/:roundNumber/closing-block-hash, /api/rounds/:roundNumber/orders
Shared API. Round and Luckotto order data used by the website surface.
Luckotto website APIsGET, POST, PATCH /api/admin/deposit-consolidation/psbt, /api/admin/partners/:partnerId/verification, /api/admin/rounds/:roundNumber/payout-txid, /api/auth/dev-login, /api/auth/logout, /api/auth/magic-link, /api/auth/sessions/revoke, /api/auth/verify, /api/health, /api/partners, /api/partners/:partnerId, /api/partners/:partnerId/api-key
Luckotto website only. Account, partner dashboard, admin, health, and local operations endpoints outside the embedded player UI.

Database tables

usersWebsite login accounts for partner owners and admins.
partner_sitesPartner tenant settings, house edge, verification status, payout metadata, and server-side API key.
deposit_addressesHash-tweaked Bitcoin deposit addresses with partner/player identity and immutable number hints. Old addresses stay valid.
paymentsConfirmed Bitcoin outputs to deposit addresses.
ticketsFinalized Luckotto tickets created from confirmed payments. Allocated numbers are indexed for claim lookup.
mempool_paymentsUnconfirmed payment hints with dropped-mempool timestamps.
roundsGlobal round windows, closing block hash, full draw order, winning ticket, winning claim numbers, and payout status.

Schema outline

CREATE TABLE partner_sites (
  id uuid PRIMARY KEY,
  owner_user_id uuid NOT NULL REFERENCES users(id),
  house_edge double precision NOT NULL DEFAULT 0,
  api_key text NOT NULL UNIQUE
);

CREATE TABLE deposit_addresses (
  id uuid PRIMARY KEY,
  partner_site_id uuid NOT NULL REFERENCES partner_sites(id),
  player_identifier text NOT NULL,
  player_uname text,
  hint_numbers integer[] NOT NULL,
  nonce integer NOT NULL,
  deposit_address text NOT NULL UNIQUE,
  deposit_hash_tweak_payload text NOT NULL,
  deposit_hash_tweak_path text NOT NULL,
  UNIQUE (partner_site_id, player_identifier, nonce)
);

CREATE TABLE tickets (
  id uuid PRIMARY KEY,
  payment_id uuid NOT NULL UNIQUE REFERENCES payments(id),
  round_number integer NOT NULL REFERENCES rounds(round_number),
  hint_numbers integer[] NOT NULL,
  numbers integer[] NOT NULL,
  price_sats bigint NOT NULL,
  explicit_fee_sats bigint NOT NULL
);

CREATE INDEX tickets_numbers_gin_idx ON tickets USING gin (numbers);

CREATE TABLE rounds (
  round_number integer PRIMARY KEY,
  closing_block_hash text,
  draw_order integer[],
  winning_ticket_id uuid,
  winning_claim_numbers integer[],
  settled_at timestamptz
);

-- /api/luckotto exposes Luckotto ticket routes over direct queries.
-- POST /api/luckotto/orders/quote returns a suggested weighted claim budget and explicit fee.
-- POST /api/luckotto/orders creates a deposit address hint and returns a valid deposit address.

Validation rules

Partner IDUUIDv7 partner site ID used in dashboard routes and iframe URLs.
API keyGenerated, displayed, stored, and rotated by the website for trusted server-side API calls only. It must not be exposed in iframe URLs, browser code, or player-visible copy.
playerUnamePublic display name, normalized and capped at 120 characters. Stored on the deposit address.
playerIdentifierPublic opaque player identifier, normalized and capped at 120 characters. Required when updating hints or listing player tickets.
houseEdgePartner-owned decimal from 0 through 0.35. It is displayed as an explicit fee rate and not hidden in odds.
Ticket IDUUIDv7 Luckotto ticket ID. Possession of the ID is enough to view public ticket status.
NumbersPlayers hint 6 through 25 unique numbers from 1 through 100. Hints guide allocation but do not reserve claims.
Allocated numbersPublic ticket number sets are the actual non-overlapping claims used for settlement.