> For the complete documentation index, see [llms.txt](https://betmatic.gitbook.io/documentation/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://betmatic.gitbook.io/documentation/api-reference/placing-bets/create-bet.md).

# Create a Bet

Bets are created as **Notifications** — a signal broadcast to one or more bookmaker sessions simultaneously. A single API call can place the same bet across every running session.

> **Prefer copy-paste code?** [Bet Examples](/documentation/api-reference/placing-bets/bet-examples.md) has 23 complete, working curl + Python examples covering every option on this page.

> **Active subscription required.** Requires an active Betmatic subscription.

***

## POST /notification/create/

Requires authentication.

```
POST /notification/create/
```

***

### Required fields

| Field    | Type   | Required | Description                                                                                                                                                                      |
| -------- | ------ | :------: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `type`   | string |    Yes   | Bet type — see [Bet Types](/documentation/api-reference/placing-bets/bet-types.md) for full explanation                                                                          |
| `sports` | string |    Yes   | `"RACING"` or a sport code e.g. `"AFL"`, `"NBA"`, `"Rugby League"`, `"Soccer"` — see [Markets & Codes](/documentation/api-reference/data/markets-and-codes.md) for the full list |

***

### Racing fields

Use when `sports` is `"RACING"`.

| Field          | Type    | Required | Description                                                                                                                                                                                                                                       |
| -------------- | ------- | :------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `competition`  | string  |    Yes   | Venue name from [Race Schedule](/documentation/api-reference/data/race-schedule.md) e.g. `"FLEMINGTON"`                                                                                                                                           |
| `code`         | string  |    Yes   | `"Galloping"` / `"Harness"` / `"Greyhounds"`                                                                                                                                                                                                      |
| `event_number` | integer |    Yes   | Race number e.g. `6`                                                                                                                                                                                                                              |
| `market`       | string  |    Yes   | Market from [Markets & Codes](/documentation/api-reference/data/markets-and-codes.md) e.g. `"Fixed Win"`                                                                                                                                          |
| `selection`    | string  |    Yes   | Runner number e.g. `"3"`. For Same Race Multi: `"runner:place,runner:place"` where place is the Top-N finish for that leg (1 = Win, 2 = Top 2, 3 = Top 3, 4 = Top 4) e.g. `"2:1,4:2"` means runner 2 to win and runner 4 to finish top 2          |
| `start_time`   | string  |    No    | The race's `startTime` copied directly from the [`GET /competition/namecodes/`](/documentation/api-reference/data/race-schedule.md) response (ISO 8601). If omitted, the system matches the next race for `competition` + `code` + `event_number` |

***

### Sports fields

Use when `sports` is not `"RACING"`.

| Field                | Type    | Required | Description                                                                       |
| -------------------- | ------- | :------: | --------------------------------------------------------------------------------- |
| `event_id`           | integer |    Yes   | Event ID from [Sports Events](/documentation/api-reference/data/sports-events.md) |
| `sports_market`      | integer |    Yes   | Market ID from `GET /event/{id}/`                                                 |
| `sports_selection`   | integer |    Yes   | Selection ID from `GET /event/{id}/`                                              |
| `handicap`           | number  |    No    | Handicap or total line copied from the selected sports selection                  |
| `accept_better_line` | boolean |    No    | Allow a more favourable handicap or total line when available                     |

> **Warning — sports bets do not return an ID.** Unlike racing bets, a successful sports create returns a plain JSON string (`"Notification has been sent."`, or `"OK"` when scheduled) with **no notification ID**. To track a sports bet, set a unique `label` on the create request, then look the notification up by that label:
>
> ```bash
> curl "https://betmatic.app/api/notification/?label=my-unique-label-001" \
>   -H "Authorization: Token YOUR_TOKEN"
> ```

***

### Stake fields

Use the field that matches your `type`.

| Field           | Type   | Used with         | Description                                |
| --------------- | ------ | ----------------- | ------------------------------------------ |
| `stake`         | number | `Fixed Wager`     | Dollar amount per session                  |
| `target_profit` | number | `Fixed Profit`    | Target profit per session                  |
| `total_wager`   | number | `High Odds First` | Total amount to distribute across sessions |

***

### Odds management

| Field                | Type    | Default | Description                                           |
| -------------------- | ------- | :-----: | ----------------------------------------------------- |
| `check_odds`         | boolean | `false` | Enable minimum odds check                             |
| `odds`               | number  |    —    | Minimum acceptable odds (requires `check_odds: true`) |
| `check_max_odds`     | boolean | `false` | Enable maximum odds check                             |
| `max_odds`           | number  |    —    | Maximum acceptable odds                               |
| `boost_if_available` | boolean | `false` | Use boosted price when available                      |
| `spg_if_available`   | boolean | `false` | Use Same Price Guarantee when available               |

***

### Session targeting

| Field                    | Type    | Default | Description                                                                                                                                                                                   |
| ------------------------ | ------- | :-----: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `bookies`                | string  |   all   | Bookmaker IDs separated by `&` e.g. `"1&2&5"` — get IDs from `GET /bookie/names/`. Bookmaker names are also accepted, but IDs are recommended                                                 |
| `target_session`         | string  |   all   | Session **IDs** separated by `&` e.g. `"12&15"` — get IDs from `GET /bookieaccount/`. Display names are **not** accepted; a non-numeric value is ignored and the bet goes to **all** sessions |
| `choose_best_odds`       | integer |   `0`   | Use only the N sessions with the best current odds (0 = all)                                                                                                                                  |
| `choose_random_accounts` | integer |   `0`   | Use N randomly selected sessions (0 = all)                                                                                                                                                    |
| `choose_random_bots`     | integer |   `0`   | Use N randomly selected connected bot instances (0 = all)                                                                                                                                     |
| `target_bot`             | string  |   all   | Target bot IDs or names separated by `&&##&&`                                                                                                                                                 |
| `ensure_total_wager`     | boolean | `false` | Treat the wager or profit target as a total across sessions. The website calls this **Ensure Total Profit** for Fixed Profit bets                                                             |
| `enable_group_bot`       | boolean | `false` | Coordinate targeting across all connected bot instances. Only takes effect when `choose_best_odds`, `choose_random_accounts` or `ensure_total_wager` is also set                              |
| `enable_group_bot_delay` | integer |   `10`  | Seconds to wait for Bot Group responses (minimum 10)                                                                                                                                          |

See [Session Targeting](/documentation/api-reference/placing-bets/session-targeting.md) for detailed explanation of each option.

***

### Bet options

| Field                     | Type    | Default | Description                                                  |
| ------------------------- | ------- | :-----: | ------------------------------------------------------------ |
| `use_bonus`               | boolean | `false` | Use bonus funds                                              |
| `allow_double_bets`       | boolean | `false` | Retry a failed session's stake on sessions that succeeded    |
| `take_sp`                 | boolean | `false` | Take starting price                                          |
| `bonus_back_if_available` | boolean |  `true` | Use a bonus-back offer when available                        |
| `label`                   | string  |    —    | Custom label for filtering on the website and in bet history |

***

### Scheduling

| Field          | Type    | Default | Description                                                            |
| -------------- | ------- | :-----: | ---------------------------------------------------------------------- |
| `is_scheduled` | boolean | `false` | Save the bet without triggering — requires manual or automatic trigger |
| `auto_trigger` | boolean | `false` | Auto-trigger at `scheduled_at` seconds before `start_time`             |
| `scheduled_at` | integer |   `60`  | Seconds before race start to auto-trigger                              |

> **Racing only.** Scheduling is supported for racing bets. Sports bets cannot be scheduled or triggered later.

See [Scheduling](/documentation/api-reference/placing-bets/scheduling.md) for detailed explanation.

***

### Market Open bets

A Market Open bet waits until a bookmaker first posts its fixed-odds market for the race, then fires immediately — useful for getting on at opening prices. Racing only. Full guide: [Market Open Bets](/documentation/api-reference/placing-bets/market-open.md).

| Field                    | Type    | Default | Description                                                                                               |
| ------------------------ | ------- | :-----: | --------------------------------------------------------------------------------------------------------- |
| `is_market_open`         | boolean | `false` | Save the bet and fire it the moment each targeted bookmaker's market opens                                |
| `delay_between_attempts` | integer |   `0`   | Seconds between retry attempts if the first placement fails (Market Open bets only; the website uses `1`) |
| `max_attempts`           | integer |   `0`   | Maximum placement attempts (Market Open bets only; the website uses `60`)                                 |

Behaviour to know:

* **One notification is created per bookmaker.** Different bookmakers open their markets at different times, so the server splits your request — the success response's `id` is an `&`-joined string of all created notification IDs, e.g. `{"id": "55401&55402&55403", "message": "Notification has been scheduled."}`. Store each ID.
* **If `bookies` is omitted**, the server targets the bookmakers known to post markets for that venue and code, filtered to bookmakers where you have a **running session** — so start your sessions before creating the bet.
* **If a bookmaker's market is already open**, that notification fires immediately; the rest wait as drafts and auto-fire on market open.
* Pending Market Open bets appear in [GET /notification/scheduled/](/documentation/api-reference/placing-bets/scheduled-bets.md) and can be cancelled with [POST /notification/{id}/cancel/](/documentation/api-reference/placing-bets/trigger-and-cancel.md).
* **Leave `is_scheduled` off** (`false`) and omit `auto_trigger`/`scheduled_at` — `is_market_open` alone saves the bet, and firing is driven by market-open detection, not by time. Don't combine Market Open with scheduling.
* **Manual trigger still works**: calling [POST /notification/{id}/trigger/](/documentation/api-reference/placing-bets/trigger-and-cancel.md) on a pending Market Open bet fires it immediately instead of waiting for the market.
* `check_odds` / `odds` and your other configured checks still apply at placement time.

See [Bet Examples](/documentation/api-reference/placing-bets/bet-examples.md) for a complete worked example.

***

### Delays

| Field                          | Type    | Default | Description                                                                    |
| ------------------------------ | ------- | :-----: | ------------------------------------------------------------------------------ |
| `bot_delay_min_time`           | integer |   `0`   | Minimum delay in seconds — applies when `choose_random_bots` is greater than 0 |
| `bot_delay_max_time`           | integer |   `0`   | Maximum delay in seconds — applies when `choose_random_bots` is greater than 0 |
| `choose_random_bot_delay_mode` | string  |    —    | `"sequential"` or `"totalised"` when randomly choosing bots                    |
| `session_delay`                | array   |   `[]`  | Per-session delays — see format below                                          |
| `bot_delay`                    | array   |   `[]`  | Per-bot delays using the same item format                                      |

**`session_delay` item format:**

| Field        | Type    | Description                                             |
| ------------ | ------- | ------------------------------------------------------- |
| `delay`      | integer | Delay in seconds                                        |
| `is_random`  | boolean | If `true`, a random value between 0 and `delay` is used |
| `identifier` | string  | The session's `display_name` from `/bookieaccount/`     |

***

### Success response — 200 OK

Returns an object with the new notification ID and a status message:

```json
{"id": 55300, "message": "Notification has been sent."}
```

If `is_scheduled` is `true`, the message confirms the bet was saved rather than sent:

```json
{"id": 55301, "message": "Notification has been scheduled."}
```

> **Check the message, not just the status code.** If none of your sessions match the bet's bookmaker and session targeting, the API still returns **200** but the message says the notification was created and **no signal was sent to the bot**. No bet is placed in that case — treat this message as a failure and review your targeting.

> **If the bot is offline, the signal is lost.** Bet signals are broadcast in real time to your currently connected bot machines — nothing is queued for later, and a bot that reconnects does **not** replay signals it missed while offline. The same applies to scheduled bets: an `auto_trigger` bet still fires at its scheduled time and is marked as triggered, but if no bot is connected at that moment the bet is simply not placed. Verify a session shows `"bot_running": true` in `GET /bookieaccount/` before creating bets, and confirm placement afterwards with `GET /bet/notification/{id}/`.

Sports notifications currently return a plain JSON string instead of an ID object — `"Notification has been sent."` on success, or `"OK"` when `is_scheduled` is `true`:

```json
"Notification has been sent."
```

Retrieve the created sports notification from `GET /notification/`, using a unique `label` when you need to identify it reliably.

| Field     | Type    | Description                                                    |
| --------- | ------- | -------------------------------------------------------------- |
| `id`      | integer | New notification ID — use for `/trigger/` and `/cancel/` calls |
| `message` | string  | Confirmation string                                            |

***

### Error codes

| Status | Cause                                                                                                            |
| :----: | ---------------------------------------------------------------------------------------------------------------- |
|   400  | Request could not be processed — the body is the string `"Internal error."`; check field names, types and values |
|   401  | Invalid or expired token                                                                                         |
|   403  | Subscription inactive or expired                                                                                 |
|   404  | Competition or event not found                                                                                   |
|   500  | Server error                                                                                                     |

**Common causes of `400 "Internal error."`** — the response body doesn't say which field is wrong, so check these first:

* `competition` doesn't match a known venue — the value must be the exact uppercase `name` from `GET /competition/namecodes/` (e.g. `"FLEMINGTON"`, not `"Flemington"`)
* The race has already run or the market is closed — the venue/`event_number` no longer resolves to an upcoming race
* An invalid `market` string — use the exact market names from `GET /bet/markets/` (e.g. `"Fixed Win"`)
* Malformed fields — wrong types (string where a number is expected), a bad `selection` format (especially Same Race Multi syntax), or an invalid `code`

***

See [Bet Examples](/documentation/api-reference/placing-bets/bet-examples.md) for complete worked examples covering all major use cases.
