Betbird API
Bet placement and virtual ticket management endpoints
Betbird API
Betbird (Betting Engine) provides bet placement APIs for virtual ticket creation, management, and bet submission. All POST requests to these endpoints must be sent through Databird, which acts as a proxy and performs authentication and pre-bet validation.
Base URL
All endpoints are relative to the base URL:
{your-base-url}/v1/betplacement/{endpoint}Overview
Betbird focuses exclusively on:
- Bet construction and validation logic
- Virtual ticket management
- Betting calculations
Note: Betbird does NOT handle:
- User authentication or registration
- Deposits or withdrawals
- Transaction processing
- Pre-bet validation checks (balance, limits, etc.)
All bet placement requests must flow through Databird, which performs these checks before proxying to Betbird.
Endpoints
Get Virtual Ticket
Retrieve details of a virtual betting ticket by its ID.
Endpoint: GET /v1/betplacement/virtualTicket/{id}
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | The virtual ticket identifier |
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| l | number | No | Language code (default: 0) |
Response Schema
The response contains the virtual ticket details including:
id(string): Ticket identifiermarkets(array): Array of market objects with betting informationsystemTypes(object): System type information including total way count. Contains:maxOverallOdds(number|null): Maximum overall odds allowedtotalWayCount(number): Total number of ways in the betsystemDescription(object): System description containing:wayDesc(string): Description of the way (e.g., "Einzel", "Doppel")wayCount(number): Number of ways
maxOddsValue(number|null): Maximum odds valuesystemType(string): System type (e.g., "SINGLES", "DOUBLES", "TREBLES")
stake(object): Stake information including stake per way and total possible win. Contains:stakePerWay(number): Stake amount per wayways(number): Number of waystotalStake(number): Total stake amount (stakePerWay × ways)totalPossibleWin(number): Total possible winningswinningsPerStakeRatio(number): Winnings per stake ratio (odds multiplier)
bonusesResponses(array): Array of bonus responsesacceptOddsChanges(boolean): Whether odds changes are acceptedfee(object): Fee information. Contains:original(number|null): Original fee amount before any adjustmentsapplicable(number|null): Applicable fee amountpercentage(number|null): Fee percentagestakeToFeeRatio(number): Stake to fee ratio
errors(array): Array of error messagescsrfPreventionSalt(string): CSRF prevention tokenreactions(array): Array of reactionssystemCombiTypes(array): Array of system combination typesfeeInclusive(boolean): Whether fee is inclusivebetBuilderCandidates(array): Array of bet builder candidatestaxFreeBet(object|null): Tax-free bet information. When present, contains:enabled(boolean): Whether tax-free bet is enabledamount(number|null): Tax-free bet amounttype(string|null): Tax-free bet type (e.g., "free_bet", "bonus")
Example Request
{
"url": "{your-base-url}/v1/betplacement/virtualTicket/1763795424810",
"method": "GET",
"queryString": "l=0"
}Example Response
{
"id": "1763795424810",
"markets": [
{
"name": "Borussia Dortmund - VfB Stuttgart",
"status": "normal",
"market": "Über/Unter (3,5): Über 3,5",
"odd": 2.25,
"resultId": 195848960510,
"eventId": 682869710,
"index": 0,
"liveEventTime": null,
"scoreText": null,
"error": null,
"resultNamePostfix": "Über 3,5",
"sportId": "soccer",
"sportRadarMatchId": 61513790,
"markets": {
"195848960510": {
"name": "Über/Unter (3,5): Über 3,5",
"error": null
}
},
"boostedOdd": 2.25,
"oddsDisplayMode": null,
"live": false,
"outright": false,
"banker": false,
"combiError": false,
"bankAvailable": false
}
],
"systemTypes": {
"maxOverallOdds": null,
"totalWayCount": 1,
"systemDescription": {
"wayDesc": "Einzel",
"wayCount": 1
},
"maxOddsValue": null,
"systemType": "SINGLES"
},
"stake": {
"stakePerWay": 5.0,
"ways": 1,
"totalStake": 5.0,
"totalPossibleWin": 11.25,
"winningsPerStakeRatio": 2.25
},
"bonusesResponses": [],
"acceptOddsChanges": false,
"fee": {
"original": null,
"applicable": null,
"percentage": null,
"stakeToFeeRatio": 0.0
},
"errors": [],
"csrfPreventionSalt": "T7OdEBgNUXxbOapxQXeM",
"reactions": [],
"systemCombiTypes": [
{
"combi": 0,
"name": "Einzel",
"count": 1,
"selected": true,
"last": true
}
],
"feeInclusive": false,
"betBuilderCandidates": [],
"taxFreeBet": null
}Example Response (With Tax-Free Bet):
{
"id": "1763795424810",
"markets": [
{
"name": "Borussia Dortmund - VfB Stuttgart",
"status": "normal",
"market": "Über/Unter (3,5): Über 3,5",
"odd": 2.25,
"resultId": 195848960510,
"eventId": 682869710,
"index": 0,
"liveEventTime": null,
"scoreText": null,
"error": null,
"resultNamePostfix": "Über 3,5",
"sportId": "soccer",
"sportRadarMatchId": 61513790,
"markets": {
"195848960510": {
"name": "Über/Unter (3,5): Über 3,5",
"error": null
}
},
"boostedOdd": 2.25,
"oddsDisplayMode": null,
"live": false,
"outright": false,
"banker": false,
"combiError": false,
"bankAvailable": false
}
],
"systemTypes": {
"maxOverallOdds": null,
"totalWayCount": 1,
"systemDescription": {
"wayDesc": "Einzel",
"wayCount": 1
},
"maxOddsValue": null,
"systemType": "SINGLES"
},
"stake": {
"stakePerWay": 5.0,
"ways": 1,
"totalStake": 5.0,
"totalPossibleWin": 11.25,
"winningsPerStakeRatio": 2.25
},
"bonusesResponses": [],
"acceptOddsChanges": false,
"fee": {
"original": null,
"applicable": null,
"percentage": null,
"stakeToFeeRatio": 0.0
},
"errors": [],
"csrfPreventionSalt": "T7OdEBgNUXxbOapxQXeM",
"reactions": [],
"systemCombiTypes": [
{
"combi": 0,
"name": "Einzel",
"count": 1,
"selected": true,
"last": true
}
],
"feeInclusive": false,
"betBuilderCandidates": [],
"taxFreeBet": {
"enabled": true,
"amount": 10.0,
"type": "free_bet"
}
}Create/Update Virtual Ticket with Market Picks
Create or update a virtual ticket with market picks and bet builder options.
Endpoint: POST /v1/betplacement/virtualTicketMarketPicksWithBetBuilder/{id}
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | The virtual ticket identifier |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| singleOutcomes | array[number] | Yes | Array of result IDs for single outcomes |
| betBuilders | array | Yes | Array of bet builder configurations |
| taxFree | boolean | No | Whether the bet is tax-free |
Response Schema
Same as Get Virtual Ticket response schema.
Example Request
{
"url": "{your-base-url}/v1/betplacement/virtualTicketMarketPicksWithBetBuilder/1763795424810",
"method": "POST",
"body": {
"singleOutcomes": [195848960510, 195848958410, 195848958510],
"betBuilders": [],
"taxFree": null
}
}Example Response
{
"id": "1763795424810",
"markets": [
{
"name": "Borussia Dortmund - VfB Stuttgart",
"status": "normal",
"market": "Über/Unter (3,5): Über 3,5",
"odd": 2.25,
"resultId": 195848960510,
"eventId": 682869710,
"index": 0,
"liveEventTime": null,
"scoreText": null,
"error": null,
"resultNamePostfix": "Über 3,5",
"sportId": "soccer",
"sportRadarMatchId": 61513790,
"markets": {
"195848960510": {
"name": "Über/Unter (3,5): Über 3,5",
"error": null
}
},
"boostedOdd": 2.25,
"oddsDisplayMode": null,
"live": false,
"outright": false,
"banker": false,
"combiError": false,
"bankAvailable": false
}
],
"systemTypes": {
"maxOverallOdds": null,
"totalWayCount": 1,
"systemDescription": {
"wayDesc": "Einzel",
"wayCount": 1
},
"maxOddsValue": null,
"systemType": "SINGLES"
},
"stake": {
"stakePerWay": 5.0,
"ways": 1,
"totalStake": 5.0,
"totalPossibleWin": 11.25,
"winningsPerStakeRatio": 2.25
},
"bonusesResponses": [],
"acceptOddsChanges": false,
"fee": {
"original": null,
"applicable": null,
"percentage": null,
"stakeToFeeRatio": 0.0
},
"errors": [],
"csrfPreventionSalt": "T7OdEBgNUXxbOapxQXeM",
"reactions": [],
"systemCombiTypes": [
{
"combi": 0,
"name": "Einzel",
"count": 1,
"selected": true,
"last": true
}
],
"feeInclusive": false,
"betBuilderCandidates": [],
"taxFreeBet": null
}Submit/Place Bet
Submit a virtual ticket to place a bet. This endpoint finalizes the bet and processes the transaction.
Endpoint: POST /v1/betplacement/virtualTicket/{id}/submit
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | The virtual ticket identifier |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| stakePerWay | number | Yes | Stake amount per way |
| acceptOddsChanges | boolean | No | Whether to accept odds changes (default: false) |
| systemType | string | No | System bet type (e.g., "SINGLES", "DOUBLES") |
Response Schema
Returns a bet confirmation object containing:
betId(string): Unique bet identifierticketId(string): Virtual ticket identifierstatus(string): Bet status (placed, pending, rejected)stake(object): Stake information. Contains:stakePerWay(number): Stake amount per waytotalStake(number): Total stake amountways(number): Number of ways
potentialWin(number): Potential winnings amountplacedAt(string): Timestamp when bet was placederrors(array): Array of error messages if bet failedbetSlip(object): Final bet slip details. Contains:markets(array): Array of market objects, each containing:eventId(number): Event identifiermarketId(number): Market identifierodd(number): Odds valuename(string): Market name
systemType(string): System bet type (e.g., "SINGLES", "DOUBLES")stake(object): Stake information (same structure as above)potentialWin(number): Potential winnings amount
Example Request
{
"url": "{your-base-url}/v1/betplacement/virtualTicket/1763795424810/submit",
"method": "POST",
"body": {
"stakePerWay": 5.0,
"acceptOddsChanges": false,
"systemType": "SINGLES"
}
}Example Response
{
"betId": "bet_1234567890",
"ticketId": "1763795424810",
"status": "placed",
"stake": {
"stakePerWay": 5.0,
"totalStake": 5.0,
"ways": 1
},
"potentialWin": 11.25,
"placedAt": "2024-01-15T14:30:00Z",
"errors": [],
"betSlip": {
"markets": [
{
"eventId": 682869710,
"marketId": 195848960510,
"odd": 2.25,
"name": "Über/Unter (3,5): Über 3,5"
}
],
"systemType": "SINGLES",
"stake": {
"stakePerWay": 5.0,
"totalStake": 5.0,
"ways": 1
},
"potentialWin": 11.25
}
}Update Stake on Virtual Ticket
Update the stake amount on an existing virtual ticket.
Endpoint: PUT /v1/betplacement/virtualTicket/{id}/stake
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | The virtual ticket identifier |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| stakePerWay | number | Yes | New stake amount per way |
Response Schema
Same as Get Virtual Ticket response schema, with updated stake information.
Example Request
{
"url": "{your-base-url}/v1/betplacement/virtualTicket/1763795424810/stake",
"method": "PUT",
"body": {
"stakePerWay": 10.0
}
}Remove Selection from Virtual Ticket
Remove a market pick from the virtual ticket. This can also be done by updating the ticket with a new selection list via the POST endpoint.
Endpoint: DELETE /v1/betplacement/virtualTicket/{id}/selections/{selectionId}
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | The virtual ticket identifier |
| selectionId | number | Yes | The result ID or selection identifier to remove |
Response Schema
Same as Get Virtual Ticket response schema, with the selection removed.
Example Request
{
"url": "{your-base-url}/v1/betplacement/virtualTicket/1763795424810/selections/195848960510",
"method": "DELETE"
}Alternative Approach: You can also remove selections by updating the virtual ticket via POST /v1/betplacement/virtualTicketMarketPicksWithBetBuilder/{id} with an updated singleOutcomes array that excludes the selection to be removed.
Clear Virtual Ticket
Clear all selections from a virtual ticket, effectively resetting it.
Endpoint: DELETE /v1/betplacement/virtualTicket/{id}
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | The virtual ticket identifier |
Response Schema
Returns a confirmation object:
success(boolean): Whether the ticket was clearedticketId(string): The cleared ticket identifier
Example Request
{
"url": "{your-base-url}/v1/betplacement/virtualTicket/1763795424810",
"method": "DELETE"
}Example Response
{
"success": true,
"ticketId": "1763795424810"
}Validate Virtual Ticket
Validate a virtual ticket before submission to check for errors or issues.
Endpoint: POST /v1/betplacement/virtualTicket/{id}/validate
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | The virtual ticket identifier |
Response Schema
Returns a validation result object:
valid(boolean): Whether the ticket is validerrors(array): Array of validation error messageswarnings(array): Array of validation warningsticket(object): Current ticket state. Contains the same structure as Get Virtual Ticket response, including:id(string): Ticket identifiermarkets(array): Array of market objectsstake(object): Stake information (see Get Virtual Ticket schema)systemTypes(object): System type information (see Get Virtual Ticket schema)errors(array): Array of error messages
Example Request
{
"url": "{your-base-url}/v1/betplacement/virtualTicket/1763795424810/validate",
"method": "POST"
}Example Response
{
"valid": true,
"errors": [],
"warnings": [],
"ticket": {
"id": "1763795424810",
"markets": [
{
"name": "Borussia Dortmund - VfB Stuttgart",
"status": "normal",
"market": "Über/Unter (3,5): Über 3,5",
"odd": 2.25,
"resultId": 195848960510,
"eventId": 682869710,
"index": 0,
"liveEventTime": null,
"scoreText": null,
"error": null,
"resultNamePostfix": "Über 3,5",
"sportId": "soccer",
"sportRadarMatchId": 61513790,
"markets": {
"195848960510": {
"name": "Über/Unter (3,5): Über 3,5",
"error": null
}
},
"boostedOdd": 2.25,
"oddsDisplayMode": null,
"live": false,
"outright": false,
"banker": false,
"combiError": false,
"bankAvailable": false
}
],
"systemTypes": {
"maxOverallOdds": null,
"totalWayCount": 1,
"systemDescription": {
"wayDesc": "Einzel",
"wayCount": 1
},
"maxOddsValue": null,
"systemType": "SINGLES"
},
"stake": {
"stakePerWay": 5.0,
"ways": 1,
"totalStake": 5.0,
"totalPossibleWin": 11.25,
"winningsPerStakeRatio": 2.25
},
"fee": {
"original": null,
"applicable": null,
"percentage": null,
"stakeToFeeRatio": 0.0
},
"errors": [],
"acceptOddsChanges": false
}
}Example Response (Invalid Ticket):
{
"valid": false,
"errors": [
"Insufficient balance",
"Odds have changed"
],
"warnings": [
"One or more selections have odds below minimum threshold"
],
"ticket": {
"id": "1763795424810",
"markets": [...],
"stake": {
"stakePerWay": 5.0,
"ways": 1,
"totalStake": 5.0,
"totalPossibleWin": 11.25,
"winningsPerStakeRatio": 2.25
},
"errors": [
"Insufficient balance",
"Odds have changed"
]
}
}