npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@bettoredge/api

v0.7.2

Published

Typed API client for BettorEdge applications

Readme

@bettoredge/api

Typed API client for BettorEdge applications. This package provides a collection of typed API functions with full TypeScript support and automatic authentication management.

Installation

npm install @bettoredge/api

Quick Start

Step 1: Initialize the API Client

Call APIOverrides.start() once at app startup:

import { APIOverrides } from '@bettoredge/api';

// In your App.tsx or root component
useEffect(() => {
  const initializeAPI = async () => {
    const authState = await APIOverrides.start({
      env: 'PRODUCTION',  // or 'STAGING', 'DEVELOPMENT', 'PRODUCTION_PROXY'
      no_cache: false     // Set to true to skip loading cached tokens
    });

    if (authState.authenticated) {
      console.log('User is already logged in!');
      // You can now call authenticated endpoints
    } else {
      console.log('User needs to log in');
    }
  };

  initializeAPI();
}, []);

Step 2a: Already Authenticated (Cached Tokens)

If authState.authenticated is true, headers are already set:

import { getPlayerProfile } from '@bettoredge/api';

// Headers are set automatically - just call the endpoint
const profile = await getPlayerProfile();
console.log(profile.player.username);

Step 2b: User Needs to Authenticate

If user is not authenticated, authenticate first:

import { authLogin, APIOverrides } from '@bettoredge/api';

// 1. Login using auth endpoint
const loginResponse = await authLogin(
  { attribute: 'email', verification_session: 'abc123' },
  { value: '[email protected]', password: 'password123' }
);

// 2. Set up API client with the auth response
await APIOverrides.authenticateApp(loginResponse, { cache: true });

// 3. Now you can call authenticated endpoints
const profile = await getPlayerProfile();

Logout

import { APIOverrides } from '@bettoredge/api';

await APIOverrides.logoutApp(); // Clears all auth headers and cached tokens

How It Works

This package uses a global axios instance with managed headers. Once you call APIOverrides.start() and authenticate, all API functions automatically include the correct headers:

  • Authorization: Bearer {token} - Set after authentication
  • x-api-key - Set automatically based on environment
  • distinctid - Device/analytics tracking (persisted in AsyncStorage)
  • sessionid - Session tracking (generated per app launch)

You only need to authenticate once and all endpoints will work throughout your app.

Available Endpoints

Authentication Endpoints (Unauthenticated)

These endpoints don't require a Bearer token - they're used to authenticate:

  • authCheck(request) - Check if user exists
  • authForgot(request) - Request password reset
  • authLogin(request, credentials) - Login with email/username/phone
  • getAuthStrategy(id) - Get registration strategy
  • executeAuthStrategy(request) - Register new account
  • verifyAuthStrategy(request) - Verify registration code
  • authenticatePhone(request) - Send phone verification
  • verifyPhone(request) - Verify phone code

Player Endpoints (Authenticated)

These endpoints require Bearer authentication:

getPlayerProfile()

Get the current authenticated player's profile.

  • Endpoint: GET /player/me
  • Authentication: Required
  • Returns: Promise<GetPlayerProfileResponse>
    • message (string): Success message
    • player (MyPlayerProps): Player profile data
    • player_premium_items (any[]): Array of premium items

Example:

// Make sure you're authenticated first!
const profile = await getPlayerProfile();
console.log(profile.player.first_name);
console.log(profile.player.email_verified);

updatePlayerName(request)

Update the current authenticated player's first and last name.

  • Endpoint: POST /player/name/update
  • Authentication: Required
  • Parameters:
    • request.first_name (string): New first name
    • request.last_name (string): New last name
  • Returns: Promise<UpdatePlayerNameResponse>
    • message (string): Success message
    • player (MyPlayerProps): Updated player profile data
  • Throws: Error if player is already verified or if update fails

Example:

// Update player name
const result = await updatePlayerName({
  first_name: 'John',
  last_name: 'Doe'
});
console.log(result.player.first_name); // 'John'
console.log(result.player.last_name); // 'Doe'

updatePlayerUsername(request)

Update the current authenticated player's username.

  • Endpoint: POST /player/username/update
  • Authentication: Required
  • Parameters: { username: string }
  • Returns: Promise<UpdatePlayerUsernameResponse> with updated player
  • Throws: Error if username is already taken

updatePlayerEmail(request)

Update the current authenticated player's email (requires confirmation).

  • Endpoint: POST /player/email/update
  • Authentication: Required
  • Parameters: { email: string }
  • Returns: Promise<UpdatePlayerEmailResponse> - pending verification message
  • Note: Email change requires confirmation via confirmPlayerEmail

confirmPlayerEmail(request)

Confirm email update with verification token.

  • Endpoint: POST /player/email/confirm
  • Authentication: Required
  • Parameters: { token: string }
  • Returns: Promise<ConfirmPlayerEmailResponse> with updated player

updatePlayerPhone(request)

Update the current authenticated player's phone number (requires confirmation).

  • Endpoint: POST /player/phone/update
  • Authentication: Required
  • Parameters: { phone: string }
  • Returns: Promise<UpdatePlayerPhoneResponse> - pending verification message
  • Note: Phone change requires confirmation via confirmPlayerPhone

confirmPlayerPhone(request)

Confirm phone update with verification token.

  • Endpoint: POST /player/phone/confirm
  • Authentication: Required
  • Parameters: { token: string }
  • Returns: Promise<ConfirmPlayerPhoneResponse> with updated player

updatePlayerDOB(request)

Update the current authenticated player's date of birth.

  • Endpoint: POST /player/dob/update
  • Authentication: Required
  • Parameters: { dob: string }
  • Returns: Promise<UpdatePlayerDOBResponse> with updated player

updatePlayerPic(request)

Update the current authenticated player's profile picture.

  • Endpoint: POST /player/pic/update
  • Authentication: Required
  • Parameters: { profile_pic: string }
  • Returns: Promise<UpdatePlayerPicResponse> with updated player

createPlayerPassword(request)

Create a password for the current authenticated player.

  • Endpoint: POST /player/password/create
  • Authentication: Required
  • Parameters: { password: string, re_password: string, current_password: string }
  • Returns: Promise<CreatePlayerPasswordResponse> with updated player
  • Throws: Error if passwords don't match

updatePlayerPassword(request)

Update the current authenticated player's password (requires confirmation).

  • Endpoint: POST /player/password/update
  • Authentication: Required
  • Parameters: { password: string, re_password: string }
  • Returns: Promise<UpdatePlayerPasswordResponse> - pending verification message
  • Note: Password change requires confirmation via confirmPlayerPassword

confirmPlayerPassword(request)

Confirm password update with verification token.

  • Endpoint: POST /player/password/confirm
  • Authentication: Required
  • Parameters: { token: string }
  • Returns: Promise<ConfirmPlayerPasswordResponse> with updated player

getPlayerBalance()

Get the current authenticated player's balance.

  • Endpoint: GET /player/balance/me
  • Authentication: Required
  • Parameters: None
  • Returns: Promise<GetPlayerBalanceResponse> with balance data
  • Throws: Error if not authenticated

Example:

const result = await getPlayerBalance();
console.log(result.player_balance.balance); // Current balance
console.log(result.player_balance.free_market_balance); // Free market balance
console.log(result.player_balance.promo_balance); // Promo balance

validatePlayerAttribute(request)

Validate if a player attribute value is available (e.g., check if username or email is already taken).

  • Endpoint: POST /v1/players/player/attribute/valid
  • Authentication: NOT Required - This is a public endpoint
  • Parameters:
    • request.attribute (string): The attribute to check ('username', 'email', 'phone')
    • request.attribute_value (string): The value to validate
  • Returns: Promise<ValidatePlayerAttributeResponse>
    • message (string): Validation message
    • valid (boolean): true if attribute is available, false if already taken
  • Throws: Error if the request fails

Example:

// Check if username is available
const result = await validatePlayerAttribute({
  attribute: 'username',
  attribute_value: 'john_doe'
});
console.log(result.valid); // true if available, false if taken

// Check if email is available
const emailCheck = await validatePlayerAttribute({
  attribute: 'email',
  attribute_value: '[email protected]'
});

Discord Integration Endpoints

getDiscordPlayer()

Get the current authenticated player's Discord connection status.

  • Endpoint: GET /discord/me
  • Authentication: Required
  • Parameters: None
  • Returns: Promise<GetDiscordPlayerResponse> with Discord connection data
  • Throws: Error if not authenticated

connectDiscord()

Start a Discord connection for the current authenticated player.

  • Endpoint: POST /discord/connect
  • Authentication: Required
  • Parameters: None
  • Returns: Promise<ConnectDiscordResponse> with auth code
  • Throws: Error if not authenticated

confirmDiscord()

Confirm a Discord connection for the current authenticated player.

  • Endpoint: POST /discord/confirm
  • Authentication: Required
  • Parameters: None
  • Returns: Promise<ConfirmDiscordResponse> with updated connection data
  • Throws: Error if not authenticated

disconnectDiscord()

Disconnect Discord from the current authenticated player.

  • Endpoint: POST /discord/disconnect
  • Authentication: Required
  • Parameters: None
  • Returns: Promise<DisconnectDiscordResponse> with reset status
  • Throws: Error if not authenticated

Example Discord Flow:

// 1. Start connection
const connectResult = await connectDiscord();
console.log(connectResult.discord_player.auth_code); // Show to user

// 2. User validates in Discord

// 3. Confirm connection
const confirmResult = await confirmDiscord();
console.log(confirmResult.discord_player.status); // 'active'

// 4. Check status anytime
const statusResult = await getDiscordPlayer();
console.log(statusResult.discord_player.discord_id);

// 5. Disconnect if needed
await disconnectDiscord();

API Key Authenticated Discord Endpoints

These Discord endpoints use x-api-key authentication (automatically set by APIOverrides.start()):

getDiscordPlayerById(discord_id)

Get Discord player by Discord ID.

  • Endpoint: GET /discord/id/:discord_id
  • Authentication: API Key (x-api-key header)
  • Parameters: discord_id: string
  • Returns: Promise<GetDiscordPlayerByIdResponse> with Discord player data
  • Throws: Error if API key is invalid
refreshDiscordToken(discord_id)

Refresh Discord token by Discord ID.

  • Endpoint: POST /discord/refresh/:discord_id
  • Authentication: API Key (x-api-key header)
  • Parameters: discord_id: string
  • Returns: Promise<RefreshDiscordTokenResponse> with refreshed token
  • Throws: Error if API key is invalid
validateDiscord(request)

Validate Discord connection.

  • Endpoint: POST /discord/validate
  • Authentication: API Key (x-api-key header)
  • Parameters: { auth_code: string, discord_id: string, username: string, image: { url: string } }
  • Returns: Promise<ValidateDiscordResponse> with validated connection data
  • Throws: Error if API key is invalid

Example:

// x-api-key is automatically set by start()
await APIOverrides.start({ env: 'PRODUCTION', no_cache: false });

// Get player by Discord ID
const player = await getDiscordPlayerById('123456789');

// Refresh token
const refreshed = await refreshDiscordToken('123456789');

// Validate connection
const validated = await validateDiscord({
  auth_code: 'code',
  discord_id: '123456789',
  username: 'User#1234',
  image: { url: 'https://...' }
});

Player Favorites Endpoints

saveFavorite(request)

Save a favorite for the current authenticated player.

  • Endpoint: POST /favorites/favorite/save
  • Authentication: Required
  • Parameters: { favorite_id: string, favorite_type: string }
  • Returns: Promise<SaveFavoriteResponse> with saved favorite data
  • Throws: Error if not authenticated

removeFavorite(request)

Remove a favorite for the current authenticated player.

  • Endpoint: POST /favorites/favorite/remove
  • Authentication: Required
  • Parameters: { player_favorite_id: string }
  • Returns: Promise<RemoveFavoriteResponse> with removed favorite data
  • Throws: Error if not authenticated

getPlayerFavorites(favorite_type?, offset?)

Get the current authenticated player's favorites.

  • Endpoint: GET /favorites/me
  • Authentication: Required
  • Parameters:
    • favorite_type?: string - Optional filter by favorite type
    • offset?: number - Optional offset for pagination (default: 0)
  • Returns: Promise<GetPlayerFavoritesResponse> with array of favorites
  • Throws: Error if not authenticated

Example:

// Save a favorite
const saved = await saveFavorite({
  favorite_id: 'game-uuid-123',
  favorite_type: 'game'
});

// Get all favorites
const allFavorites = await getPlayerFavorites();

// Get favorites by type
const gameFavorites = await getPlayerFavorites('game');

// Get favorites with pagination
const paginated = await getPlayerFavorites('game', 20);

// Remove a favorite
await removeFavorite({
  player_favorite_id: 'favorite-uuid-123'
});

Promo Endpoints

Bearer Token Authenticated Endpoints

These endpoints require Bearer token authentication. Ensure you're authenticated via APIOverrides.authenticateApp() before calling.

getMyCodeRequest()

Get the current authenticated player's code request including promo, referral, and reward information.

  • Endpoint: GET /v1/promos/request/me
  • Authentication: Required
  • Parameters: None
  • Returns: Promise<GetMyCodeRequestResponse>
    • message (string): Success message
    • promo (PromoProps | undefined): Promo details if available
    • code_request (CodeRequestProps | undefined): Code request information
    • player_referral (PlayerReferralProps | undefined): Player referral details
    • referrer (PublicPlayerProps | undefined): Referrer player information
    • reward_option (RewardOptionProps | undefined): Reward option details
  • Throws: Error if not authenticated or if the request fails

Example:

// Get the authenticated player's code request
const result = await getMyCodeRequest();
console.log(result.message); // 'Successfully retrieved code request'

if (result.promo) {
  console.log(result.promo.description);
  console.log(result.promo.type); // 'referral_code' | 'promo_code' | etc.
}

if (result.code_request) {
  console.log(result.code_request.referral_code);
  console.log(result.code_request.status); // 'requested' | 'fulfilled' | etc.
}

if (result.referrer) {
  console.log(result.referrer.username); // Username of the referrer
}

Markets Endpoints

API Key Authenticated Endpoints

These endpoints require API key authentication (x-api-key header). The API key is automatically set when you call APIOverrides.start().

getAllMarkets(status?)

Get all markets with optional status filter.

  • Endpoint: GET /v1/markets/all
  • Authentication: API Key (x-api-key)
  • Parameters:
    • status (optional): Filter by status ('active' | 'inactive')
  • Returns: Promise<GetAllMarketsResponse> with markets array
  • Throws: Error if the request fails

Example:

// Get all markets
const result = await getAllMarkets();
console.log(result.markets);

// Get only active markets
const activeMarkets = await getAllMarkets('active');
console.log(activeMarkets.markets);

getAvailableMarkets(league_ids?)

Get available markets with optional league filter.

  • Endpoint: GET /v1/markets/available
  • Authentication: API Key (x-api-key)
  • Parameters:
    • league_ids (optional): Comma-separated league IDs to filter by
  • Returns: Promise<GetAvailableMarketsResponse> with available markets
  • Throws: Error if the request fails

Example:

// Get all available markets
const result = await getAvailableMarkets();
console.log(result.available_markets);

// Get available markets for specific leagues
const leagueMarkets = await getAvailableMarkets('league-1,league-2');
console.log(leagueMarkets.available_markets);

getActiveEvents(league_id?, type?, expanded?)

Get active events with optional filters.

  • Endpoint: GET /v1/events/active
  • Authentication: API Key (x-api-key)
  • Parameters:
    • league_id (optional): Filter by league ID
    • type (optional): Filter by event type
    • expanded (optional): Set to 'true' to return full event objects instead of just IDs
  • Returns: Promise<GetActiveEventsResponse> with event IDs and optionally full events
  • Throws: Error if the request fails

Example:

// Get all active event IDs
const result = await getActiveEvents();
console.log(result.event_ids);

// Get active events for a specific league
const leagueEvents = await getActiveEvents('league-123');
console.log(leagueEvents.event_ids);

// Get full event objects
const expandedEvents = await getActiveEvents(undefined, undefined, 'true');
console.log(expandedEvents.events);

searchEvents(request)

Search for events by search value.

  • Endpoint: POST /v1/events/search
  • Authentication: API Key (x-api-key)
  • Parameters: SearchEventsRequest object with:
    • search_value (required): Search term to find events
  • Returns: Promise<SearchEventsResponse> with matching events
  • Throws: Error if the request fails

Example:

// Search for events
const result = await searchEvents({
  search_value: 'Lakers'
});
console.log(result.message); // 'Success'
console.log(result.events);

getActiveTournaments(league_id?, expanded?)

Get active tournaments with optional filters.

  • Endpoint: GET /v1/tournaments/active
  • Authentication: API Key (x-api-key)
  • Parameters:
    • league_id (optional): Filter by league ID
    • expanded (optional): Set to 'true' to return full tournament objects instead of just IDs
  • Returns: Promise<GetActiveTournamentsResponse> with tournament IDs and optionally full tournaments
  • Throws: Error if the request fails

Example:

// Get all active tournament IDs
const result = await getActiveTournaments();
console.log(result.tournament_ids);

// Get active tournaments for a specific league
const leagueTournaments = await getActiveTournaments('league-123');
console.log(leagueTournaments.tournament_ids);

// Get full tournament objects
const expandedTournaments = await getActiveTournaments(undefined, 'true');
console.log(expandedTournaments.tournament_ids);

searchTournaments(request)

Search for tournaments by search value.

  • Endpoint: POST /v1/tournaments/search/value
  • Authentication: API Key (x-api-key)
  • Parameters: SearchTournamentsRequest object with:
    • search_value (required): Search term to find tournaments
    • offset (optional): Offset for pagination
  • Returns: Promise<SearchTournamentsResponse> with matching tournaments
  • Throws: Error if the request fails

Example:

// Search for tournaments
const result = await searchTournaments({
  search_value: 'Masters'
});
console.log(result.message); // 'Successfully retrieved tournaments'
console.log(result.tournaments);

// Search with offset for pagination
const paginatedResult = await searchTournaments({
  search_value: 'PGA',
  offset: 10
});
console.log(paginatedResult.tournaments);

getTournamentById(tournament_id)

Get tournament details by ID.

  • Endpoint: GET /v1/tournaments/tournament/:tournament_id
  • Authentication: API Key (x-api-key)
  • Parameters:
    • tournament_id (required): Tournament ID
  • Returns: Promise<GetTournamentByIdResponse> with tournament details
  • Throws: Error if the request fails

Example:

// Get tournament by ID
const result = await getTournamentById('tournament-uuid-123');
console.log(result.message); // 'Successfully retrieved tournament'
console.log(result.tournament);

Golf Tournament Endpoints

These endpoints provide detailed golf tournament data including leaderboards, scorecards, and statistics.

getGolfDetails(tournament_id, year?)

Get golf tournament details including leaderboard, athletes, course info, and active round.

  • Endpoint: GET /v1/tournaments/golf/details/:tournament_id
  • Authentication: API Key (x-api-key)
  • Parameters:
    • tournament_id (required): Tournament ID
    • year (optional): Year filter for historical data
  • Returns: Promise<GetGolfDetailsResponse> with:
    • message (string): Success message
    • golf_leaders (GolfLeaderProps[]): Leaderboard entries with positions, scores, and round details
    • athletes (AthleteProps[]): Athlete details for participants
    • golf_course (GolfCourseProps): Course information including holes and par
    • active_round (number): Current active round number
  • Throws: Error if the request fails

Example:

// Get golf tournament details
const result = await getGolfDetails('tournament-uuid-123');
console.log(result.golf_leaders); // Leaderboard entries
console.log(result.athletes); // Athlete details
console.log(result.golf_course); // Course information
console.log(result.active_round); // Current round number

// Get golf details for a specific year
const historicResult = await getGolfDetails('tournament-uuid-123', '2024');

getGolfScorecard(tournament_id, athlete_id?, round_number?)

Get golf scorecard for a specific athlete in a tournament round.

  • Endpoint: GET /v1/tournaments/golf/scorecard/:tournament_id
  • Authentication: API Key (x-api-key)
  • Parameters:
    • tournament_id (required): Tournament ID
    • athlete_id (optional): Athlete ID to filter scorecard
    • round_number (optional): Round number to filter scorecard
  • Returns: Promise<GetGolfScorecardResponse> with:
    • message (string): Success message
    • golf_scorecards (GolfScorecardProps[]): Hole-by-hole scorecard data
  • Throws: Error if the request fails

Example:

// Get all scorecards for a tournament
const result = await getGolfScorecard('tournament-uuid-123');
console.log(result.golf_scorecards);

// Get scorecard for specific athlete and round
const athleteScorecard = await getGolfScorecard(
  'tournament-uuid-123',
  'athlete-uuid-456',
  '2'
);
console.log(athleteScorecard.golf_scorecards);

getGolfStatistics(tournament_id)

Get golf tournament statistics including hole-by-hole and round statistics.

  • Endpoint: GET /v1/tournaments/golf/statistics/:tournament_id
  • Authentication: API Key (x-api-key)
  • Parameters:
    • tournament_id (required): Tournament ID
  • Returns: Promise<GetGolfStatisticsResponse> with:
    • message (string): Success message
    • golf_tournament_statistics (GolfTournamentStatisticsProps): Full statistics including round and hole data
    • prior_year (boolean): Whether stats are from prior year
  • Throws: Error if the request fails

Example:

// Get golf tournament statistics
const result = await getGolfStatistics('tournament-uuid-123');
console.log(result.golf_tournament_statistics); // Full statistics object
console.log(result.golf_tournament_statistics.round_statistics); // Round-by-round stats
console.log(result.prior_year); // Whether stats are from prior year

getActiveMatches()

Get all active matches.

  • Endpoint: GET /v1/matches/active
  • Authentication: API Key (x-api-key)
  • Returns: Promise<GetActiveMatchesResponse> with active matches
  • Throws: Error if the request fails

Example:

// Get all active matches
const result = await getActiveMatches();
console.log(result.message); // 'Successfully retrieved matches'
console.log(result.matches);

getMatchesByTournamentId(tournament_id)

Get matches for a specific tournament.

  • Endpoint: GET /v1/matches/tournament/:tournament_id
  • Authentication: API Key (x-api-key)
  • Parameters:
    • tournament_id (required): Tournament ID
  • Returns: Promise<GetMatchesByTournamentIdResponse> with tournament and matches
  • Throws: Error if the request fails

Example:

// Get matches for a tournament
const result = await getMatchesByTournamentId('tournament-uuid-123');
console.log(result.message); // 'Successfully retrieved matches'
console.log(result.tournament);
console.log(result.matches);

getMatchById(match_id)

Get match details by ID.

  • Endpoint: GET /v1/matches/match/:match_id
  • Authentication: API Key (x-api-key)
  • Parameters:
    • match_id (required): Match ID
  • Returns: Promise<GetMatchByIdResponse> with match details
  • Throws: Error if the request fails

Example:

// Get match by ID
const result = await getMatchById('match-uuid-123');
console.log(result.message); // 'Successfully retrieved matches'
console.log(result.match);

getLeagues(status?)

Get all leagues with optional status filter.

  • Endpoint: GET /v1/leagues/
  • Authentication: API Key (x-api-key)
  • Parameters:
    • status (optional): Filter by status ('active' | 'inactive')
  • Returns: Promise<GetLeaguesResponse> with leagues array and timestamp
  • Throws: Error if the request fails

Example:

// Get all leagues
const result = await getLeagues();
console.log(result.message); // 'Successfully retrieved leagues'
console.log(result.leagues);
console.log(result.timestamp);

// Get only active leagues
const activeLeagues = await getLeagues('active');
console.log(activeLeagues.leagues);

Bearer Token Authenticated Endpoints

These endpoints require Bearer token authentication. You must call APIOverrides.authenticateApp() before using these endpoints.

placeOrder(request)

Place an order in the market.

  • Endpoint: POST /v1/orders/order/place
  • Authentication: Bearer token required
  • Parameters: PlaceOrderRequest object with:
    • order_context_hash (required): Order context hash string
    • price (required): Order price (number)
    • amount (required): Order amount (number)
    • market_type (required): Market type string
    • expire_time (optional): Order expiration time
    • key (optional): Optional key string
  • Returns: Promise<PlaceOrderResponse> with order context
  • Throws: Error if not authenticated or if the request fails

Example:

// Place an order
const orderContext = await placeOrder({
  order_context_hash: 'context-hash-123',
  price: 0.55,
  amount: 100,
  market_type: 'standard',
  expire_time: '2024-12-31T23:59:59Z'
});
console.log(orderContext);

cancelOrder(request)

Cancel a single order.

  • Endpoint: POST /v1/orders/order/cancel
  • Authentication: Bearer token required
  • Parameters: CancelOrderRequest object with:
    • order_id (required): Order ID to cancel
  • Returns: Promise<CancelOrderResponse> with cancelled order
  • Throws: Error if not authenticated or if the request fails

Example:

// Cancel an order
const result = await cancelOrder({
  order_id: 'order-uuid-123'
});
console.log(result.message); // 'Successfully cancelled order'
console.log(result.order);

bulkCancelOrders(request)

Cancel multiple orders in bulk.

  • Endpoint: POST /v1/orders/bulk/cancel
  • Authentication: Bearer token required
  • Parameters: BulkCancelOrderRequest object with:
    • order_ids (required): Array of order IDs to cancel
  • Returns: Promise<BulkCancelOrderResponse> with cancelled orders array
  • Throws: Error if not authenticated or if the request fails

Example:

// Cancel multiple orders
const result = await bulkCancelOrders({
  order_ids: ['order-uuid-1', 'order-uuid-2', 'order-uuid-3']
});
console.log(result.message); // 'Successfully cancelled order'
console.log(result.orders);

getH2HHistory(h2h_id)

Get head-to-head order history.

  • Endpoint: GET /v1/orders/h2h/history/:h2h_id
  • Authentication: Bearer token required
  • Parameters:
    • h2h_id (required): Head-to-head ID
  • Returns: Promise<GetH2HHistoryResponse> with H2H order history
  • Throws: Error if not authenticated or if the request fails

Example:

// Get H2H history
const result = await getH2HHistory('h2h-uuid-123');
console.log(result.message); // 'Successfully retrieved h2h stats'
console.log(result.orders);

acceptH2H(request)

Accept a head-to-head request.

  • Endpoint: POST /v1/orders/h2h/accept
  • Authentication: Bearer token required
  • Parameters: AcceptH2HRequest object with:
    • order_id (required): Order ID to accept
  • Returns: Promise<AcceptH2HResponse> with accepted order
  • Throws: Error if not authenticated or if the request fails

Example:

// Accept H2H request
const result = await acceptH2H({
  order_id: 'order-uuid-123'
});
console.log(result.message); // 'Successfully accepted h2h request'
console.log(result.order);

declineH2H(request)

Decline a head-to-head request.

  • Endpoint: POST /v1/orders/h2h/decline
  • Authentication: Bearer token required
  • Parameters: DeclineH2HRequest object with:
    • order_id (required): Order ID to decline
  • Returns: Promise<DeclineH2HResponse> with declined order
  • Throws: Error if not authenticated or if the request fails

Example:

// Decline H2H request
const result = await declineH2H({
  order_id: 'order-uuid-123'
});
console.log(result.message); // 'Successfully declined h2h request'
console.log(result.order);

getMyRebates()

Get my collectable rebates.

  • Endpoint: GET /v1/orders/rebates/me
  • Authentication: Bearer token required
  • Returns: Promise<GetMyRebatesResponse> with player commission rebates array
  • Throws: Error if not authenticated or if the request fails

Example:

// Get my rebates
const result = await getMyRebates();
console.log(result.message); // 'Successfully retrieved rebates'
console.log(result.player_commission_rebates);

collectRebate(request)

Collect a rebate.

  • Endpoint: POST /v1/orders/rebate/collect
  • Authentication: Bearer token required
  • Parameters: CollectRebateRequest object with:
    • player_commission_rebate_id (required): Rebate ID to collect
  • Returns: Promise<CollectRebateResponse> with collected rebate
  • Throws: Error if not authenticated or if the request fails

Example:

// Collect a rebate
const result = await collectRebate({
  player_commission_rebate_id: 'rebate-uuid-123'
});
console.log(result.message); // 'Successfully collected rebate!'
console.log(result.player_commission_rebate);

getRebateById(player_commission_rebate_id)

Get rebate by ID.

  • Endpoint: GET /v1/orders/rebate/:player_commission_rebate_id
  • Authentication: Bearer token required
  • Parameters:
    • player_commission_rebate_id (required): Rebate ID
  • Returns: Promise<GetRebateByIdResponse> with rebate details
  • Throws: Error if not authenticated or if the request fails

Example:

// Get rebate by ID
const result = await getRebateById('rebate-uuid-123');
console.log(result.message); // 'Successfully retrieved rebate'
console.log(result.player_commission_rebate);

Flash Market Endpoints (Admin)

These endpoints require admin role with Bearer token authentication:

generateFlashMarket(request)

Generate a flash market preview using Claude AI.

  • Endpoint: POST /admin/flash-market/generate
  • Authentication: Required (Admin Role)
  • Parameters: FlashMarketGenerateRequest object with:
    • prompt (required): Text prompt describing the market to generate
    • poll_campaign_id (required): Campaign ID to associate with
    • num_options (optional): Number of options to generate
    • use_web_search (optional): Whether to use web search for context
    • contest_type (optional): Contest type
    • contest_id (optional): Contest ID
    • base_stake (optional): Base stake amount
    • min_stake (optional): Minimum stake amount
    • max_stake (optional): Maximum stake amount
  • Returns: Promise<FlashMarketGenerateResponse>
    • message (string): Success message
    • poll_campaign_id (string): Campaign ID
    • preview (FlashMarketPreview): Generated preview with question, options, reasoning, and sources
  • Throws: Error if prompt or poll_campaign_id is missing, or if generation fails

Example:

const result = await generateFlashMarket({
  prompt: 'Will the Lakers win tonight?',
  poll_campaign_id: 'campaign-uuid-123',
  num_options: 3,
  use_web_search: true
});
console.log(result.preview.poll_question);
console.log(result.preview.poll_options);
console.log(result.preview.reasoning);

createFlashMarket(request)

Create a flash market from reviewed preview data.

  • Endpoint: POST /admin/flash-market/create
  • Authentication: Required (Admin Role)
  • Parameters: FlashMarketCreateRequest object with:
    • poll_campaign_id (required): Campaign ID to create the poll under
    • poll_question (required): The poll question text
    • poll_options (required): Array of 2-6 options, each with option_name, option_value, initial_odds, and priority. Odds must sum to 1.0
    • contest_type (optional): Contest type
    • contest_id (optional): Contest ID
    • base_stake (optional): Base stake amount (default: 100)
    • min_stake (optional): Minimum stake amount (default: 10)
    • max_stake (optional): Maximum stake amount (default: 1000)
  • Returns: Promise<FlashMarketCreateResponse>
    • message (string): Success message
    • poll (PollProps): The created poll
    • poll_options (PollOptionProps[]): The created poll options
  • Throws: Error if required fields are missing, options count is invalid, odds don't sum to 1.0, or creation fails

Example:

const result = await createFlashMarket({
  poll_campaign_id: 'campaign-uuid-123',
  poll_question: 'Will the Lakers win tonight?',
  poll_options: [
    { option_name: 'Yes', option_value: 'yes', initial_odds: 0.6, priority: 1 },
    { option_name: 'No', option_value: 'no', initial_odds: 0.4, priority: 2 }
  ],
  min_stake: 10,
  max_stake: 1000
});
console.log(result.poll);
console.log(result.poll_options);

Poll Campaign Management Endpoints

These endpoints manage poll campaigns and polls. Most require Bearer token authentication.

getMyActiveCampaigns()

Get the current admin's active campaigns.

  • Endpoint: GET /v1/polls/me/active
  • Authentication: Required (Bearer token)
  • Returns: Promise<GetMyActiveCampaignsResponse> with campaigns array
  • Throws: Error if not authenticated

Example:

const result = await getMyActiveCampaigns();
console.log(result.campaigns);

createCampaign(request)

Create a new poll campaign.

  • Endpoint: POST /v1/polls/campaigns/campaign/create
  • Authentication: Required (Bearer token)
  • Parameters: CreateCampaignRequest with:
    • name (required): Campaign name
  • Returns: Promise<CreateCampaignResponse> with created campaign

Example:

const result = await createCampaign({ name: 'My Flash Markets' });
console.log(result.campaign.poll_campaign_id);

getCampaignDetails(poll_campaign_id)

Get campaign details by ID.

  • Endpoint: GET /v1/polls/campaigns/campaign/:poll_campaign_id
  • Authentication: Not required
  • Parameters: poll_campaign_id (required): Campaign ID
  • Returns: Promise<GetCampaignDetailsResponse> with campaign details

Example:

const result = await getCampaignDetails('campaign-uuid-123');
console.log(result.campaign);

getCampaignPolls(poll_campaign_id)

Get all polls in a campaign.

  • Endpoint: GET /v1/polls/campaign/:poll_campaign_id
  • Authentication: Required (Bearer token)
  • Parameters: poll_campaign_id (required): Campaign ID
  • Returns: Promise<GetCampaignPollsResponse> with polls array

Example:

const result = await getCampaignPolls('campaign-uuid-123');
console.log(result.polls);

getPollDetails(poll_id)

Get poll details with options.

  • Endpoint: GET /v1/polls/poll/:poll_id
  • Authentication: Required (Bearer token)
  • Parameters: poll_id (required): Poll ID
  • Returns: Promise<GetPollDetailsResponse> with poll and poll_options

Example:

const result = await getPollDetails('poll-uuid-123');
console.log(result.poll);
console.log(result.poll_options);

createPoll(request)

Create a new poll in a campaign.

  • Endpoint: POST /v1/polls/poll/create
  • Authentication: Required (Bearer token)
  • Parameters: CreatePollRequest with:
    • poll_campaign_id (required): Campaign ID
    • poll_question (required): Poll question text
    • poll_options (optional): Array of option previews
    • poll_type (optional): 'select' or 'input'
    • minimum_stake, max_stake, base_stake (optional): Stake settings
  • Returns: Promise<CreatePollResponse> with created poll and options

Example:

const result = await createPoll({
  poll_campaign_id: 'campaign-uuid-123',
  poll_question: 'Who will win?',
  poll_options: [
    { option_name: 'Team A', option_value: 'team_a', initial_odds: 0.5, priority: 1 },
    { option_name: 'Team B', option_value: 'team_b', initial_odds: 0.5, priority: 2 }
  ]
});

updatePoll(request)

Update an existing poll.

  • Endpoint: POST /v1/polls/poll/update
  • Authentication: Required (Bearer token)
  • Parameters: UpdatePollRequest with poll_id and fields to update
  • Returns: Promise<UpdatePollResponse> with updated poll

activatePoll(request)

Activate a pending poll.

  • Endpoint: POST /v1/polls/poll/activate
  • Parameters: ActivatePollRequest with poll_id
  • Returns: Promise<ActivatePollResponse> with activated poll

closePoll(request)

Close a poll, optionally selecting a winning option.

  • Endpoint: POST /v1/polls/poll/close
  • Parameters: ClosePollRequest with poll_id and optional winning_option_id
  • Returns: Promise<ClosePollResponse> with closed poll

voidPoll(request)

Void a poll.

  • Endpoint: POST /v1/polls/poll/void
  • Authentication: Required (Bearer token)
  • Parameters: VoidPollRequest with poll_id and optional void_reason
  • Returns: Promise<VoidPollResponse> with voided poll

deletePoll(request)

Delete a poll.

  • Endpoint: POST /v1/polls/poll/delete
  • Authentication: Required (Bearer token)
  • Parameters: DeletePollRequest with poll_id
  • Returns: Promise<DeletePollResponse> with success message

createPollOption(request)

Create a new option for a poll.

  • Endpoint: POST /v1/polls/poll/option/create
  • Parameters: CreatePollOptionRequest with poll_id, option_name, option_value, optional initial_odds and priority
  • Returns: Promise<CreatePollOptionResponse> with created option

updatePollOption(request)

Update an existing poll option.

  • Endpoint: POST /v1/polls/poll/option/update
  • Parameters: UpdatePollOptionRequest with poll_option_id and fields to update
  • Returns: Promise<UpdatePollOptionResponse> with updated option

Admin-Only Endpoints

These endpoints require admin role (player.role === 'admin'):

manualVouchPlayer(request)

Manually vouch a player (Admin only).

  • Endpoint: POST /vouch/manual
  • Authentication: Required (Admin Role)
  • Parameters: { player_id: string }
  • Returns: Promise<ManualVouchPlayerResponse> with updated player
  • Throws: Error if not admin or if the request fails
  • Note: Requires authenticated user to have admin role

Example:

// Admin user only
const result = await manualVouchPlayer({
  player_id: 'player-uuid-123'
});
console.log(result.message); // 'Successfully vouched player'

reverifyVouchPlayer(request)

Request reverification for a player's vouch status (Admin only).

  • Endpoint: POST /vouch/reverify
  • Authentication: Required (Admin Role)
  • Parameters: { player_id: string }
  • Returns: Promise<ReverifyVouchPlayerResponse> with updated player
  • Throws: Error if not admin or if the request fails
  • Note: Requires authenticated user to have admin role

Example:

// Admin user only
const result = await reverifyVouchPlayer({
  player_id: 'player-uuid-123'
});
console.log(result.message); // 'Successfully requested re-verification'

failVouchPlayer(request)

Fail a player's vouch status (Admin only).

  • Endpoint: POST /vouch/fail
  • Authentication: Required (Admin Role)
  • Parameters: { player_id: string }
  • Returns: Promise<FailVouchPlayerResponse> with updated player
  • Throws: Error if not admin or if the request fails
  • Note: Requires authenticated user to have admin role

Example:

// Admin user only
const result = await failVouchPlayer({
  player_id: 'player-uuid-123'
});
console.log(result.message); // 'Successfully failed vouch'

resetVouchPlayer(request)

Reset a player's vouch status (Admin only).

  • Endpoint: POST /vouch/reset
  • Authentication: Required (Admin Role)
  • Parameters: { player_id: string }
  • Returns: Promise<ResetVouchPlayerResponse> with updated player
  • Throws: Error if not admin or if the request fails
  • Note: Requires authenticated user to have admin role

Example:

// Admin user only
const result = await resetVouchPlayer({
  player_id: 'player-uuid-123'
});
console.log(result.message); // 'Successfully reset vouch status'

Type Imports

All types are imported from @bettorEdge/types:

import type { MyPlayerProps, PlayerBalanceProps, DiscordPlayerProps, PlayerFavoriteProps, MarketProps, MarketLiquidityProps, PlayerCommissionRebateProps, EventProps, TournamentProps, MatchProps, LeagueProps, AuthStateProps, GolfLeaderProps, GolfCourseProps, GolfScorecardProps, GolfTournamentStatisticsProps, AthleteProps, PollProps, PollOptionProps } from '@bettorEdge/types';
import type {
  GetPlayerProfileResponse,
  UpdatePlayerNameRequest,
  UpdatePlayerNameResponse,
  UpdatePlayerUsernameRequest,
  UpdatePlayerUsernameResponse,
  UpdatePlayerEmailRequest,
  UpdatePlayerEmailResponse,
  ConfirmPlayerEmailRequest,
  ConfirmPlayerEmailResponse,
  UpdatePlayerPhoneRequest,
  UpdatePlayerPhoneResponse,
  ConfirmPlayerPhoneRequest,
  ConfirmPlayerPhoneResponse,
  UpdatePlayerDOBRequest,
  UpdatePlayerDOBResponse,
  UpdatePlayerPicRequest,
  UpdatePlayerPicResponse,
  CreatePlayerPasswordRequest,
  CreatePlayerPasswordResponse,
  UpdatePlayerPasswordRequest,
  UpdatePlayerPasswordResponse,
  ConfirmPlayerPasswordRequest,
  ConfirmPlayerPasswordResponse,
  GetPlayerBalanceResponse,
  GetDiscordPlayerResponse,
  ConnectDiscordResponse,
  ConfirmDiscordResponse,
  DisconnectDiscordResponse,
  GetDiscordPlayerByIdResponse,
  RefreshDiscordTokenResponse,
  ValidateDiscordRequest,
  ValidateDiscordResponse,
  ManualVouchPlayerRequest,
  ManualVouchPlayerResponse,
  ReverifyVouchPlayerRequest,
  ReverifyVouchPlayerResponse,
  FailVouchPlayerRequest,
  FailVouchPlayerResponse,
  ResetVouchPlayerRequest,
  ResetVouchPlayerResponse,
  SaveFavoriteRequest,
  SaveFavoriteResponse,
  RemoveFavoriteRequest,
  RemoveFavoriteResponse,
  GetPlayerFavoritesResponse,
  GetAllMarketsResponse,
  GetAvailableMarketsResponse,
  PlaceOrderRequest,
  PlaceOrderResponse,
  CancelOrderRequest,
  CancelOrderResponse,
  BulkCancelOrderRequest,
  BulkCancelOrderResponse,
  GetH2HHistoryResponse,
  AcceptH2HRequest,
  AcceptH2HResponse,
  DeclineH2HRequest,
  DeclineH2HResponse,
  GetMyRebatesResponse,
  CollectRebateRequest,
  CollectRebateResponse,
  GetRebateByIdResponse,
  GetActiveEventsResponse,
  SearchEventsRequest,
  SearchEventsResponse,
  GetActiveTournamentsResponse,
  SearchTournamentsRequest,
  SearchTournamentsResponse,
  GetTournamentByIdResponse,
  GetActiveMatchesResponse,
  GetMatchesByTournamentIdResponse,
  GetMatchByIdResponse,
  GetLeaguesResponse,
  GetGolfDetailsResponse,
  GetGolfScorecardResponse,
  GetGolfStatisticsResponse,
  FlashMarketOptionPreview,
  FlashMarketPreview,
  FlashMarketGenerateRequest,
  FlashMarketGenerateResponse,
  FlashMarketCreateRequest,
  FlashMarketCreateResponse
} from '@bettoredge/api';

Competitions API (CompetitionsApi)

Public Competition Endpoints

getActivePublicCompetitions()

Retrieves all active public competitions. Uses soft authentication to enrich with user data if authenticated.

  • Endpoint: GET /v2/competitions/public (TP_SVC_API)
  • Authentication: Optional (softAuthenticate)
  • Returns: Promise<GetActivePublicCompetitionsResponse> with competitions array

getActivePublicSeasons()

Retrieves all active public competition seasons.

  • Endpoint: GET /v2/competitions/seasons/public (TP_SVC_API)
  • Authentication: Optional (softAuthenticate)
  • Returns: Promise<GetActivePublicSeasonsResponse> with competition_seasons array

getActivePublicSquares()

Retrieves all active public squares competitions.

  • Endpoint: GET /v1/squares/public (TP_SVC_API)
  • Authentication: Optional (softAuthenticate)
  • Returns: Promise<GetActivePublicSquaresResponse> with squares_competitions array

getCompetitionOptions()

Retrieves all available competition types, result types, and payout types.

  • Endpoint: GET /v1/competitions/options (TP_SVC_API)
  • Authentication: None (public)
  • Returns: Promise<GetCompetitionOptionsResponse> with competition_types, competition_result_types, competition_payout_types

getPrivateEngage(code)

Searches for a private competition by invite code. Returns matching competition, bracket, squares, or season.

  • Endpoint: POST /v2/competitions/private (TP_SVC_API)
  • Authentication: Optional (softAuthenticate)
  • Parameters: code: string
  • Returns: Promise<GetPrivateEngageResponse> with optional competition, squares_competition, competition_season, bracket_competition

Company Bulk Endpoints

searchCompanies(search_value, offset)

Search for companies by name. Requires authentication.

  • Endpoint: POST /v1/companies/search (AUTH_SVC_API)
  • Authentication: Bearer token
  • Parameters: search_value: string, offset: number
  • Returns: Promise<SearchCompaniesResponse> with companies array

getCompaniesByIds(company_ids)

Retrieves multiple companies by their IDs. Public endpoint.

  • Endpoint: POST /v1/companies/bulk/get (AUTH_SVC_API)
  • Authentication: None (public)
  • Parameters: company_ids: string[]
  • Returns: Promise<GetCompaniesByIdsResponse> with companies array

Player Bulk Endpoints

getPlayersByIds(player_ids)

Retrieves multiple players by their IDs. Requires authentication.

  • Endpoint: POST /v1/players/bulk/get (AUTH_SVC_API)
  • Authentication: Bearer token
  • Parameters: player_ids: string[]
  • Returns: Promise<GetPlayersByIdsResponse> with players array

Poll/Campaign Endpoints

getActivePublicCampaigns(offset?)

Retrieves all active public poll/trivia campaigns with pagination.

  • Endpoint: GET /v1/polls/public/active (AUTH_SVC_API)
  • Authentication: None (public)
  • Parameters: offset?: number (defaults to 0)
  • Returns: Promise<GetActivePublicCampaignsResponse> with poll_campaigns array

Bracket Bulk Endpoints

getBulkBrackets(bracket_ids)

Retrieves multiple brackets by their IDs. Public endpoint.

  • Endpoint: POST /v1/brackets/bulk/get (EVENT_SVC_API)
  • Authentication: None (public)
  • Parameters: bracket_ids: string[]
  • Returns: Promise<GetBulkBracketsResponse> with brackets array

Configuration

Environment Selection

The API client uses different base URLs based on the environment:

await APIOverrides.start({ env: 'PRODUCTION' });     // Production API
await APIOverrides.start({ env: 'STAGING' });        // Staging API
await APIOverrides.start({ env: 'DEVELOPMENT' });    // Local development
await APIOverrides.start({ env: 'PRODUCTION_PROXY' }); // Production via proxy

Token Management

Tokens are automatically:

  • Cached to AsyncStorage when you call authenticateApp({ cache: true })
  • Loaded on start({ no_cache: false })
  • Refreshed automatically on 401 errors
  • Cleared on logoutApp()

Error Handling

All API functions throw errors that can be caught with try/catch:

try {
  const profile = await getPlayerProfile();
} catch (error) {
  if (error.response) {
    // Server responded with error status
    console.error('Status:', error.response.status);
    console.error('Message:', error.response.data.message);
  } else if (error.request) {
    // Request made but no response received
    console.error('No response received');
  } else {
    // Error setting up the request
    console.error('Error:', error.message);
  }
}

Troubleshooting

Error: 401 Unauthorized

Problem: "Failed to fetch player profile" or 401 error

Solutions:

  1. Did you call APIOverrides.start()?

    await APIOverrides.start({ env: 'PRODUCTION', no_cache: false });
  2. Did you authenticate after login?

    const loginResponse = await authLogin(request, credentials);
    await APIOverrides.authenticateApp(loginResponse, { cache: true });
  3. Check if user is authenticated:

    const authState = await APIOverrides.start({ env: 'PRODUCTION', no_cache: false });
    if (!authState.authenticated) {
      // User needs to log in
    }

Error: 403 Forbidden

Problem: "Authentication session has expired"

Solution: The refresh token failed. User needs to log in again:

await APIOverrides.logoutApp(); // Clear old tokens
// Show login screen

Headers Not Set

Problem: API calls aren't including authentication headers

Solution: Make sure you call APIOverrides.start() at app initialization (not in component mount):

// ✅ Correct - in App.tsx or _layout.tsx
useEffect(() => {
  APIOverrides.start({ env: 'PRODUCTION', no_cache: false });
}, []);

// ❌ Wrong - in a screen component
useEffect(() => {
  APIOverrides.start({ env: 'PRODUCTION', no_cache: false });
}, []); // This runs too late

Token Not Persisting

Problem: User has to log in every time app restarts

Solution: Make sure you're caching tokens:

// When authenticating
await APIOverrides.authenticateApp(authResponse, { cache: true }); // ✅ cache: true

// When starting
await APIOverrides.start({ env: 'PRODUCTION', no_cache: false }); // ✅ no_cache: false

Wrong Environment

Problem: Getting 404 or connection errors

Solution: Check your environment setting:

// Make sure you're using the right environment
await APIOverrides.start({
  env: 'PRODUCTION',    // Not 'DEVELOPMENT' if you want prod
  no_cache: false
});

Adding New Endpoints

CRITICAL INSTRUCTIONS FOR CLAUDE CODE:

When adding endpoints to this package, you MUST follow these steps exactly. You will be provided:

  1. The endpoint URL and HTTP method
  2. The path to the server file where the endpoint is implemented

IMPORTANT: Before proceeding with implementation, you MUST ASK THE USER which file to add the endpoint to. Do NOT assume the file location based on the endpoint domain. Wait for explicit confirmation from the user.

Your responsibilities:

Step 1: Read the Server Implementation AND Route Prefix

REQUIRED: You must do TWO things:

A) Read the route file to understand:

  • Exact request body/query parameters and their types
  • Exact response structure and types
  • Authentication requirements (Bearer token, API key, etc.)
  • Error responses and status codes
  • The endpoint path (e.g., /player/balance/me)

B) Check the routes/index.ts file for the prefix:

  • The routes/index.ts file (in the same directory as the route file) defines the prefix
  • Example: If routes/index.ts has app.use('/v1/players', players)
  • And the route file has router.get('/player/balance/me')
  • Then the full path is: /v1/players/player/balance/me

Path to check: /Users/jamesseils/Desktop/Desktop/BettorEdge/[service-name]/routes/index.ts

CRITICAL: You MUST check both files to get the complete endpoint URL

Step 2: Use Types from @bettorEdge/types - NEVER RECREATE

🚨🚨🚨 ABSOLUTE CRITICAL RULE - ZERO TOLERANCE 🚨🚨🚨

NEVER EVER EVER CREATE AN INTERFACE IN THIS PACKAGE THAT REPRESENTS A DATABASE MODEL

YOU MUST:

  1. FIRST check if the type exists in @bettorEdge/types package at /Users/jamesseils/Desktop/bettordev/components/packages/types/src/player.types.ts
  2. IF IT EXISTS - Import it from @bettorEdge/types and use it
  3. IF IT DOES NOT EXIST - STOP IMMEDIATELY and tell the user:
    • "The type [TypeName] does not exist in @bettorEdge/types"
    • "I found it in the server at [server file path]"
    • "Please add it to @bettorEdge/types first, then I can continue"
  4. WAIT for the user to add the type to @bettorEdge/types
  5. NEVER EVER EVER create the interface yourself in this api package OR in the types package

THIS MEANS:

  • If you see MyPlayerProps in server response → Import from @bettorEdge/types
  • If you see PlayerBalanceProps in server response → Check @bettorEdge/types, IF NOT THERE: STOP AND TELL USER
  • If you see GameProps in server response → Import from @bettorEdge/types
  • ANY type that represents data from the database must come from @bettorEdge/types
  • YOU (Claude) will NEVER add types to @bettorEdge/types - only the user will do this

WORKFLOW - YOU MUST FOLLOW THIS EXACTLY:

  1. Read server implementation
  2. Identify what types the server returns (e.g., player_balance: PlayerBalanceProps)
  3. Search @bettorEdge/types/src/player.types.ts for that type
  4. IF NOT FOUND:
    • STOP WORK IMMEDIATELY
    • Tell user: "I need PlayerBalanceProps which doesn't exist in @bettorEdge/types. I found it at [server path]. Please add it to @bettorEdge/types first."
    • WAIT for user confirmation
  5. AFTER USER ADDS IT: Import it from @bettorEdge/types
  6. Create only the Request/Response wrapper types in this api package

Example - CORRECT:

import type { MyPlayerProps } from '@bettorEdge/types';

export interface GetPlayerProfileResponse {
  message: string;
  player: MyPlayerProps;  // ✅ Using existing type from @bettorEdge/types
  player_premium_items: any[];
}

Example - ABSOLUTELY WRONG - NEVER DO THIS:

// ❌❌❌ NEVER EVER DO THIS - ZERO TOLERANCE ❌❌❌
export interface PlayerBalanceProps {
  player_balance_id: string;
  player_id: string;
  // ... ANY interface representing database data
}

// This is WRONG - Claude must NEVER create this
// Claude must STOP and ask the user to add it to @bettorEdge/types first

Step 3: Confirm File Location with User

🚨 REQUIRED: ASK THE USER BEFORE PROCEEDING

Before implementing the endpoint, you MUST ask the user which file to use. Present them with options based on the endpoint domain, but wait for their explicit confirmation.

Example question to ask:

"I found the endpoint POST /player/name/update in the server file. This appears to be a player-related endpoint. Should I add this to:

  • src/players.ts (recommended for player endpoints)
  • src/auth.ts (if auth-related)
  • A new file (please specify the name)

Which file should I use?"

Common file organization:

  • Player-related: src/players.ts
  • Game-related: src/games.ts (create if needed)
  • Bet-related: src/bets.ts (create if needed)
  • Auth-related: src/auth.ts (already exists)

DO NOT proceed to Step 4 until the user confirms the file location.

Step 4: Define Request and Response Types

Request Types:

  • If request body/params exist, create an interface matching the EXACT server types
  • Import any types from @bettorEdge/types that the server uses
  • Use optional properties (?) exactly as the server defines them

Response Types:

  • Create response interface matching EXACT server response structure
  • Import return types from @bettorEdge/types (e.g., MyPlayerProps, GameProps)
  • Include error response types if documented

Example:

import type { MyPlayerProps, BetProps } from '@bettorEdge/types';

// Request type - matching server exactly
export interface CreateBetRequest {
  game_id: string;
  amount: number;
  bet_type: 'SPREAD' | 'MONEYLINE' | 'TOTAL';
  selection?: string;  // Optional on server = optional here
}

// Response type - using imported types from @bettorEdge/types
export interface CreateBetResponse {
  message: string;
  bet: BetProps;  // ✅ Imported from @bettorEdge/types
  player: MyPlayerProps;  // ✅ Imported from @bettorEdge/types
}

Step 5: Document the Endpoint

Include comprehensive JSDoc with:

  1. Brief description - what the endpoint does
  2. Endpoint path - exact HTTP method and URL (e.g., POST /v1/bets)
  3. Authentication - Required or Optional (specify Bearer, API key, etc.)
  4. Parameters - describe each parameter with types
  5. Returns - describe success response
  6. Throws - describe error conditions
  7. Example - working code example showing usage

Template:

/**
 * [Brief description of what this endpoint does]
 *
 * **Authentication: [Required/Optional]** - [Specify type: Bearer token, API key, etc.]
 *
 * Endpoint: `[HTTP_METHOD] /path/to/endpoint`
 *
 * @param request - [Description of request parameters]
 * @returns [Description of success response]
 * @throws Error if [describe error conditions from server]
 *
 * @example
 * ```typescript
 * // [Show realistic usage example]
 * const result = await yourEndpoint(request);
 * console.log(result.data);
 * ```
 */

Step 6: Implement the Function

Follow this exact pattern:

For Authenticated Endpoints:

export const yourEndpoint = async (
  request: YourRequestType
): Promise<YourResponseType> => {
  try {
    const endpoints = APIOverrides.getEndpoints();
    const AUTH_SVC_API = endpoints.AUTH_SVC_API as string;

    // Uses global axios instance with Bearer token set by APIOverrides
    const response = await axios.post<YourResponseType>(
      `${AUTH_SVC_API}/your/endpoint/path`,
      request
    );
    return response.data;
  } catch (error: any) {
    // Return structured error response if available
    if (error.response?.data) {
      throw new Error(error.response.data.message || 'Operation failed');
    }
    throw error;
  }
};

For Unauthenticated Endpoints (like auth/login):

export const yourEndpoint = async (
  request: YourRequestType
): Promise<YourResponseType> => {
  try {
    const endpoints = APIOverrides.getEndpoints();
    const AUTH_SVC_API = endpoints.AUTH_SVC_API as string;

    // No Bearer token needed for unauthenticated endpoints
    const response = await axios.post<YourResponseType>(
      `${AUTH_SVC_API}/your/endpoint/path`,
      request
    );
    return response.data;
  } catch (error: any) {
    if (error.response?.data) {
      throw new Error(error.response.data.message || 'Operation failed');
    }
    throw error;
  }
};

Step 7: Export from index.ts

Add your new function to src/index.ts:

// Your domain endpoints
export { yourFunction } from './your-domain';
export type { YourRequestType, YourResponseType } from './your-domain';

Step 8: Update README Documentation

Add your endpoint to the "Available Endpoints" section:

For Authenticated Endpoints:

#### `yourEndpoint(request)`

[Brief description]

- **Endpoint**: `POST /your/endpoint/path`
- **Authentication**: Required
- **Returns**: `Promise<YourResponseType>`
  - `field1` (type): Description
  - `field2` (type): Description

**Example**:
\`\`\`typescript
const result = await yourEndpoint({ param: 'value' });
console.log(result.data);
\`\`\`

Step 9: Rebuild and Verify

npm run build
npm run typescript

Ensure both commands complete without errors.


Summary Checklist for Adding Endpoints

  • [ ] Read the server implementation file to understand exact types
  • [ ] ASK USER which file to add the endpoint to - DO NOT ASSUME
  • [ ] Wait for user confirmation before proceeding
  • [ ] Check @bettorEdge/types for existing types - NEVER RECREATE
  • [ ] Import required types from @bettorEdge/types
  • [ ] Create request/response interfaces matching server EXACTLY
  • [ ] Add comprehensive JSDoc documentation
  • [ ] Implement function following the pattern above
  • [ ] Handle errors with structured error messages
  • [ ] Export from src/index.ts
  • [ ] Document in README "Available Endpoints" section
  • [ ] Run npm run build and npm run typescript to verify
  • [ ] Verify no type errors or compilation issues

Development

# Type check
npm run typescript

# Build
npm run build

Dependencies

  • @bettorEdge/types: Shared type definitions
  • axios: HTTP client

License

MIT