How the Odds API Handles Postponed, Delayed and Cancelled Events
August 26, 2026

How the Odds API Handles Postponed, Delayed and Cancelled Events
Most of an odds API integration is straightforward until a game doesn't start on time. Then the question becomes what your code should see, and the answer depends on decisions made upstream of your request. This is the behaviour that generates more support questions than any other part of our event data, so it's worth setting out exactly what happens and why.
Postponement is messier than it looks
Sometimes a postponed game gets a new date within the hour and nothing much is disrupted. Sometimes a fixture sits unscheduled for months. Which of those you get depends on the league, the sport, the region, and occasionally on a governing body that hasn't decided yet.
The hard part is that whether a postponed game will eventually be rescheduled or quietly dropped is often not knowable at the moment it is postponed, and that call can arrive at any point afterwards. An API doesn't get to stay undecided. Every event in the feed has to hold some state, and that state has to be one your code can act on.
What we do
If a postponed game doesn't have a confirmed schedule within a short window of the original postponement, we mark the event as cancelled.
If the game is subsequently rescheduled, we create a new event rather than reinstating the original one.
Why a new event rather than a reinstated one
Reinstating a cancelled event sounds tidier, but it breaks things that have already responded to the cancellation. A bet tracker may have voided its tickets. A cache may have dropped the fixture. A warehouse may have written a final row. Anything that treated the cancellation as settled now has to unwind it, and a record moving from cancelled back to upcoming is a transition most systems are never written to expect.
Creating a new event avoids that entirely. The cancelled record stays accurate about what it describes, which is a fixture that could not be confirmed. The new record describes the game that is actually going to be played. Neither one has to lie about its own history.
What this means in practice
You will sometimes see two entries for the same fixture, one marked cancelled and one upcoming. That is expected behaviour rather than duplicate data.
The important consequence is that the two entries have different eventID values. If your ingestion de-duplicates on something like home team plus away team plus date, the rescheduled game will look like a conflict with the cancelled one. De-duplicate on eventID and the problem disappears.
It also means a stored eventID doesn't follow a game to its new date. If you saved an eventID against a user's bet, a watchlist entry, or a cached row, it will keep resolving to the cancelled record. Anything long-lived that references an event should re-check status.cancelled rather than assuming the ID stays valid.
Filtering cancelled events out
The cheapest place to deal with cancelled events is in the request. /events takes a cancelled parameter, so you can exclude them before the response is assembled:
curl "https://api.sportsgameodds.com/v2/events?leagueID=NFL&cancelled=false&oddsAvailable=true" \
-H "x-api-key: YOUR_API_KEY"
Pass cancelled=true to look at only the cancelled ones, which is useful when reconciling your own store against ours. Omit the parameter and you get both, which is what you want if you are branching on state yourself.
In the response, event state lives under status:
{
"status": {
"started": false,
"completed": false,
"cancelled": false,
"ended": false,
"live": false,
"delayed": false,
"displayLong": "Upcoming",
"finalized": false
}
}
status.delayed covers a game that has slipped but is still expected to be played, so it's the flag to watch if you want to surface a delay to users before anything is cancelled. status.cancelled is the one that tells you this record is finished.
Use the event-level flag, not the odds-level one
Individual odds carry a cancelled flag too, at odds.<oddID>.cancelled. It is tempting to reach for it when you care about a specific market, but its meaning is different from the event-level flag and considerably less intuitive, and we have plans to change how it works.
Until then, build against status.cancelled at the event level. It is the flag we recommend, and it is the one whose behaviour will stay stable.
If you settle bets
Grading logic that waits for status.finalized needs a cancelled branch, or a cancelled fixture will sit in your open-tickets queue forever waiting on a result that is never coming. Check status.cancelled in the same pass that checks status.finalized, and void rather than grade when it's set.
The rest of the settlement flow, including reading each market's score and knowing when a result is safe to trust, is covered in the bet tracking and settlement guide.
Read More: Getting started with the odds API | Live and in-play odds | NFL odds API guide
Why do I see two events for the same game?
How do I stop cancelled events appearing in my feed?
Should I use the cancelled flag on an odds market?
Does a rescheduled game keep its original eventID?
How should my bet grading handle a cancelled event?
Build on data that tells you what happened
Odds, scores, and event status in one feed, with a free tier to test against.