Your scoring system stays the source of truth. LIGR takes one fact per event and turns it into the score, the clock, the statistics and every graphic that reads them.
To score a LIGR match from your own system, create the match with POST /v2/matches, set the lineup, then post one fact for every event to POST /v2/matches/{matchId}/facts. LIGR computes the score, the clock, the statistics and the graphics from those facts. Correct a fact by updating or deleting it, and read the result back from the match summary. This guide follows Score a match from your system in the LIGR developer docs, which walks one football match with curl.
Who this is for
Leagues, federations and data teams that already capture match events, in a scoring app, a stats system or a results database, and want LIGR graphics and highlights to follow them. You need a write key with matches:write for the match, the lineup and the facts, plus teams:write if you add players to a roster. The REST API quick start covers keys and scopes.
What you can build
| Sport | What you build | What the docs give you |
|---|---|---|
| Football | A pitchside or press-box scoring app that posts goals, cards and substitutions as they happen | The full fact name list, the periods and the error messages |
| Tennis | A tournament system that creates singles and doubles matches, with player competitors in place of teams | competitorsType of singles or doubles, and entityType: player rows |
| AFL | A team-sheet tool that sends each side's starters and bench before the first bounce | PUT /v2/matches/{matchId}/lineup, which open overlays show at once |
| Basketball, netball, American football | A stats system that posts its events as facts and reconciles against the summary after every game | The same endpoints. Fact name references for these sports are marked coming soon, so ask your LIGR contact for the names |
The fact endpoint does not check name against a list. A name LIGR does not know is stored and drives nothing: no score, no statistic and no graphic. That is why the sport-specific names matter.
How it works: one football match
Find the ids you need
A match belongs to a competition, takes place at a venue and has two teams. Read them once with GET /v1/competitions, GET /v1/competitions/{competitionId}/teams and GET /v1/venues, and keep the ids.
Create the match
Send POST /v2/matches with the competition, the venue, the kick-off date in ISO 8601 with its timezone, competitorsType and a competitors array. Each competitor row has an entityId, an entityType and meta.isHome. Keep the id in the answer.
Set the lineup
Send the starters and the bench of each team to PUT /v2/matches/{matchId}/lineup. Graphics use the lineup to show the teams, list the scorers and fill the player variables. Each player must be on the team roster: add a missing one with POST /v1/teams/{teamId}/players, and set shorter graphics names with gfxFirstName and gfxLastName. The call replaces the lineup of each team you send.
Start the first half
Post a PERIOD_STARTED fact with periodNumber: 1. The match goes live and the clock starts. Periods start in order: a PERIOD_STARTED that skips a period returns 400.
Post each event as a fact
name is the event, periodNumber is the period it happened in, teamId and playerId say who, and data carries the sport-specific detail. This goal is copied from the docs guide:
curl -X POST 'https://api.ligr.live/rest/v2/matches/1188213/facts' \
-H "Authorization: Bearer $LIGR_API_KEY" \
-H 'Content-Type: application/json' \
-d '{ "name": "GOAL", "periodNumber": 1, "teamId": 1, "playerId": 501, "data": { "shotOnTarget": true } }'
The answer carries the fact id. Keep it: you need it to correct or delete the fact. date defaults to the time LIGR receives the fact. Send it when your system timestamps the event, because LIGR derives the match minute from date and the period start.
Correct a mistake
Update a fact with POST /v2/matches/{matchId}/facts/{factId}, sending only the fields that change, for example a new playerId. Delete a fact that never happened with DELETE on the same path. LIGR recomputes the score and the statistics. A period fact can be deleted only while it is the most recent one.
Close the match and read it back
Post PERIOD_FINISHED for the last period. To end a match early, call POST /v2/matches/{matchId}/finish. To cancel or abandon it, call …/cancel or …/abandon. Then read GET /v2/matches/{matchId}/summary, the score, periods, clock and statistics LIGR folded from your facts, and compare it with your own state.
Football periods and fact names
A football match runs through periods 0 pre-match, 1 first half, 2 half time, 3 second half and 4 full time. PERIOD_FINISHED with 1 stops the clock and moves the match into half time, and PERIOD_STARTED with 3 starts the second half. The most used fact names:
name | Event |
|---|---|
GOAL, OWN_GOAL, PENALTY_SCORED | A goal. An own goal counts for the other team |
YELLOW_CARD, SECOND_YELLOW_CARD, RED_CARD | A card for teamId and playerId |
SUBSTITUTION | Counts in substitutions. Optional data { "off": 501, "on": 502 } swaps the players in the lineup |
CORNER_WON, OFFSIDE, SAVE | A corner, an offside or a save |
SHOT_ON_TARGET, SHOT_OFF_TARGET, SHOT_BLOCKED | A shot |
FREE_KICK_CONCEDED, PENALTY_CONCEDED | Fouls. FOUL on its own does not change fouls |
CLOCK_STOPPED, CLOCK_STARTED | Stop or start the clock inside a period |
SHOOTOUT_GOAL, SHOOTOUT_MISS | A penalty shootout attempt |
Possession, passes, tackles and other Opta-only statistics come only from a data provider feed. No fact sets them. The full table is in the scoring guide, and the request shape is on Create a fact.
Keep LIGR in step with your system
- Post every fact once. LIGR does not deduplicate facts. Make a retry safe: read the match back before you post again.
- Post in the order things happened. The summary is folded in fact order.
- Confirm with webhooks. Subscribe a webhook to
factandsummaryevents to see what LIGR computed, as it computes it. See sports webhooks.
| Error | Cause |
|---|---|
400 Could not find period 'N' | periodNumber is not a period of this match |
400 Period has already started | A second PERIOD_STARTED for the current period |
400 Invalid lineup | A player is not on the roster, or a team does not play in the match. details names each bad value |
404 No fact found with id 'N' | The fact does not belong to the match in the path |
Other sports. The fact endpoint is the same for every sport, and only the fact names change. The docs mark the fact name references for tennis, basketball, Australian rules, rugby league, rugby union, cricket, netball and the other sports as coming soon. Until they are published, ask your LIGR contact for the names. GET /v2/schemas/sports/{sport} returns the data shape graphics read for each sport.
Frequently asked questions
How do I send live scores to LIGR from my own system?
Create the match with POST /v2/matches, set the lineup with PUT /v2/matches/{matchId}/lineup, then post one fact per event to POST /v2/matches/{matchId}/facts with a matches:write key. LIGR computes the score, the clock, the statistics and the graphics from the facts.
Does LIGR deduplicate facts?
No. Post every fact once, in the order it happened, because LIGR folds the summary in fact order. Keep the id of every fact you post, so you can correct or delete it.
How do I fix a wrong goal scorer or a disallowed goal?
Update the fact with POST /v2/matches/{matchId}/facts/{factId}, sending only the fields that change, such as playerId. Delete a fact that never happened with DELETE on the same path. LIGR recomputes the score and the statistics.
Which sports can I score through the LIGR API?
The fact endpoint is the same for every sport, and only the fact names change. Football has a full fact name reference in the docs. For other sports, including tennis, basketball, Australian rules, netball and American football, the references are marked coming soon, so ask your LIGR contact for the fact names.
How do I check what LIGR computed?
Read GET /v2/matches/{matchId}/summary, which returns the score, the periods, the clock and the statistics, and compare it with your own state after every match. A webhook subscribed to fact and summary events confirms each change as it happens.
Connect your scoring system
The scoring guide walks a full football match with curl, with every fact name, period and error message.