@bettoredge/api
v0.7.2
Published
Typed API client for BettorEdge applications
Maintainers
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/apiQuick 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 tokensHow 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 authenticationx-api-key- Set automatically based on environmentdistinctid- 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 existsauthForgot(request)- Request password resetauthLogin(request, credentials)- Login with email/username/phonegetAuthStrategy(id)- Get registration strategyexecuteAuthStrategy(request)- Register new accountverifyAuthStrategy(request)- Verify registration codeauthenticatePhone(request)- Send phone verificationverifyPhone(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 messageplayer(MyPlayerProps): Player profile dataplayer_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 namerequest.last_name(string): New last name
- Returns:
Promise<UpdatePlayerNameResponse>message(string): Success messageplayer(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 balancevalidatePlayerAttribute(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 messagevalid(boolean):trueif attribute is available,falseif 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 typeoffset?: 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 messagepromo(PromoProps | undefined): Promo details if availablecode_request(CodeRequestProps | undefined): Code request informationplayer_referral(PlayerReferralProps | undefined): Player referral detailsreferrer(PublicPlayerProps | undefined): Referrer player informationreward_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 IDtype(optional): Filter by event typeexpanded(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:
SearchEventsRequestobject 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 IDexpanded(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:
SearchTournamentsRequestobject with:search_value(required): Search term to find tournamentsoffset(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 IDyear(optional): Year filter for historical data
- Returns:
Promise<GetGolfDetailsResponse>with:message(string): Success messagegolf_leaders(GolfLeaderProps[]): Leaderboard entries with positions, scores, and round detailsathletes(AthleteProps[]): Athlete details for participantsgolf_course(GolfCourseProps): Course information including holes and paractive_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 IDathlete_id(optional): Athlete ID to filter scorecardround_number(optional): Round number to filter scorecard
- Returns:
Promise<GetGolfScorecardResponse>with:message(string): Success messagegolf_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 messagegolf_tournament_statistics(GolfTournamentStatisticsProps): Full statistics including round and hole dataprior_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 yeargetActiveMatches()
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:
PlaceOrderRequestobject with:order_context_hash(required): Order context hash stringprice(required): Order price (number)amount(required): Order amount (number)market_type(required): Market type stringexpire_time(optional): Order expiration timekey(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:
CancelOrderRequestobject 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:
BulkCancelOrderRequestobject 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:
AcceptH2HRequestobject 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:
DeclineH2HRequestobject 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:
CollectRebateRequestobject 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:
FlashMarketGenerateRequestobject with:prompt(required): Text prompt describing the market to generatepoll_campaign_id(required): Campaign ID to associate withnum_options(optional): Number of options to generateuse_web_search(optional): Whether to use web search for contextcontest_type(optional): Contest typecontest_id(optional): Contest IDbase_stake(optional): Base stake amountmin_stake(optional): Minimum stake amountmax_stake(optional): Maximum stake amount
- Returns:
Promise<FlashMarketGenerateResponse>message(string): Success messagepoll_campaign_id(string): Campaign IDpreview(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:
FlashMarketCreateRequestobject with:poll_campaign_id(required): Campaign ID to create the poll underpoll_question(required): The poll question textpoll_options(required): Array of 2-6 options, each withoption_name,option_value,initial_odds, andpriority. Odds must sum to 1.0contest_type(optional): Contest typecontest_id(optional): Contest IDbase_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 messagepoll(PollProps): The created pollpoll_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:
CreateCampaignRequestwith: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:
CreatePollRequestwith:poll_campaign_id(required): Campaign IDpoll_question(required): Poll question textpoll_options(optional): Array of option previewspoll_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:
UpdatePollRequestwithpoll_idand fields to update - Returns:
Promise<UpdatePollResponse>with updated poll
activatePoll(request)
Activate a pending poll.
- Endpoint:
POST /v1/polls/poll/activate - Parameters:
ActivatePollRequestwithpoll_id - Returns:
Promise<ActivatePollResponse>with activated poll
closePoll(request)
Close a poll, optionally selecting a winning option.
- Endpoint:
POST /v1/polls/poll/close - Parameters:
ClosePollRequestwithpoll_idand optionalwinning_option_id - Returns:
Promise<ClosePollResponse>with closed poll
voidPoll(request)
Void a poll.
- Endpoint:
POST /v1/polls/poll/void - Authentication: Required (Bearer token)
- Parameters:
VoidPollRequestwithpoll_idand optionalvoid_reason - Returns:
Promise<VoidPollResponse>with voided poll
deletePoll(request)
Delete a poll.
- Endpoint:
POST /v1/polls/poll/delete - Authentication: Required (Bearer token)
- Parameters:
DeletePollRequestwithpoll_id - Returns:
Promise<DeletePollResponse>with success message
createPollOption(request)
Create a new option for a poll.
- Endpoint:
POST /v1/polls/poll/option/create - Parameters:
CreatePollOptionRequestwithpoll_id,option_name,option_value, optionalinitial_oddsandpriority - Returns:
Promise<CreatePollOptionResponse>with created option
updatePollOption(request)
Update an existing poll option.
- Endpoint:
POST /v1/polls/poll/option/update - Parameters:
UpdatePollOptionRequestwithpoll_option_idand 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>withcompetitionsarray
getActivePublicSeasons()
Retrieves all active public competition seasons.
- Endpoint:
GET /v2/competitions/seasons/public(TP_SVC_API) - Authentication: Optional (softAuthenticate)
- Returns:
Promise<GetActivePublicSeasonsResponse>withcompetition_seasonsarray
getActivePublicSquares()
Retrieves all active public squares competitions.
- Endpoint:
GET /v1/squares/public(TP_SVC_API) - Authentication: Optional (softAuthenticate)
- Returns:
Promise<GetActivePublicSquaresResponse>withsquares_competitionsarray
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>withcompetition_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 optionalcompetition,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>withcompaniesarray
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>withcompaniesarray
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>withplayersarray
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>withpoll_campaignsarray
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>withbracketsarray
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 proxyToken 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:
Did you call
APIOverrides.start()?await APIOverrides.start({ env: 'PRODUCTION', no_cache: false });Did you authenticate after login?
const loginResponse = await authLogin(request, credentials); await APIOverrides.authenticateApp(loginResponse, { cache: true });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 screenHeaders 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 lateToken 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: falseWrong 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:
- The endpoint URL and HTTP method
- 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:
- FIRST check if the type exists in
@bettorEdge/typespackage at/Users/jamesseils/Desktop/bettordev/components/packages/types/src/player.types.ts - IF IT EXISTS - Import it from
@bettorEdge/typesand use it - 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"
- "The type
- WAIT for the user to add the type to @bettorEdge/types
- NEVER EVER EVER create the interface yourself in this api package OR in the types package
THIS MEANS:
- If you see
MyPlayerPropsin server response → Import from@bettorEdge/types - If you see
PlayerBalancePropsin server response → Check@bettorEdge/types, IF NOT THERE: STOP AND TELL USER - If you see
GamePropsin 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:
- Read server implementation
- Identify what types the server returns (e.g.,
player_balance: PlayerBalanceProps) - Search
@bettorEdge/types/src/player.types.tsfor that type - IF NOT FOUND:
- STOP WORK IMMEDIATELY
- Tell user: "I need
PlayerBalancePropswhich doesn't exist in @bettorEdge/types. I found it at [server path]. Please add it to @bettorEdge/types first." - WAIT for user confirmation
- AFTER USER ADDS IT: Import it from
@bettorEdge/types - 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 firstStep 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/updatein 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/typesthat 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:
- Brief description - what the endpoint does
- Endpoint path - exact HTTP method and URL (e.g.,
POST /v1/bets) - Authentication - Required or Optional (specify Bearer, API key, etc.)
- Parameters - describe each parameter with types
- Returns - describe success response
- Throws - describe error conditions
- 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 typescriptEnsure 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/typesfor 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 buildandnpm run typescriptto verify - [ ] Verify no type errors or compilation issues
Development
# Type check
npm run typescript
# Build
npm run buildDependencies
@bettorEdge/types: Shared type definitionsaxios: HTTP client
License
MIT
