Edit through REST
Every change the graphics builder makes to a working Rive graphic is one REST operation. Each operation locks the graphic for the request, validates the whole configuration, saves, and publishes a live update to open builder tabs.
All routes sit under /rest/v2/themes/{themeId}/rive-graphics/{graphicId}. Write routes need themes:write.
Each write returns updatedAt, entityId, and the full stateMachine.
Optimistic concurrency
Section titled “Optimistic concurrency”Send ifUnchangedSince with the updatedAt you last read. A changed draft answers 409 TARGET_CHANGED.
Opening a graphic in the dashboard Graphics Builder takes its edit lock.
While that builder tab is open, every REST write answers 409 LOCKED.
Close the builder tab, then retry.
The ligr-graphic CLI sends ifUnchangedSince for you and retries once. See Command line.
Errors
Section titled “Errors”An error body has message and code. A 4xx answer can also have details, an array with one entry for each problem.
| Field | Content |
|---|---|
code | The error code, for example INVALID_CONFIGURATION, UNKNOWN_REFERENCE or INVALID_EXPRESSION. |
details[].field | The path of the value that failed. The path points into the request body or into the graphic configuration, for example controlVariables[stage].defaultValue or dataBindings[Main.homeScore].expression. |
details[].reason | What is wrong with the value, for example must be a JSON number. |
{ "message": "INVALID_CONFIGURATION", "code": "INVALID_CONFIGURATION", "details": [{ "field": "controlVariables[stage].defaultValue", "reason": "must be a JSON number" }]}A 500 answer has only message. The ligr-graphic CLI prints each detail on its own line as field: reason.
Control variables
Section titled “Control variables”api POST "themes/$THEME_ID/rive-graphics/$GRAPHIC_ID/control-variables" \ --data '{"name":"stage","type":"enum","options":["GROUP A","FINAL"],"defaultValue":"GROUP A"}'api PATCH "themes/$THEME_ID/rive-graphics/$GRAPHIC_ID/control-variables/$CONTROL_ID" --data '{"defaultValue":"FINAL"}'api DELETE "themes/$THEME_ID/rive-graphics/$GRAPHIC_ID/control-variables/$CONTROL_ID?force=true"Types: string, number, boolean, enum, and the entity types team, player, match, fact, stat, teamStat, period, set, round, court.
Entity types carry a server-derived dataSchema in the response. hide is reserved.
A control variable default must have the JSON type of the variable. Send 0, not "0".
Removing a variable that an expression references answers 422 UNKNOWN_REFERENCE; force=true blanks those expressions.
Data bindings
Section titled “Data bindings”Binding ids contain dots, so URL-encode them.
B="themes/$THEME_ID/rive-graphics/$GRAPHIC_ID/data-bindings"api PATCH "$B/Main.homeScore" --data '{"expression":"$d.1.score"}'api PUT "$B/Main.badge/exposure" --data '{"name":"Home badge","expression":"$d.1.id","required":true,"entityType":"team"}'api PUT "$B/Main.badge/image-transform" --data '{"fit":"cover","outWidth":256,"outHeight":256}'api PUT "$B/Main.players%5B%5D/source-array" --data '{"arrayPath":"1.lineup"}'api POST "$B/Main.players%5B%5D/elements"api DELETE "$B/Main.players%5B%5D/elements/0"api PUT "$B/Main.players%5B%5D/elements/order" --data '{"order":[1,0]}'Exposure and image transforms apply to image bindings only. A source array applies to one list binding per graphic.
A source array is a path into the match data without the $d prefix, for example 1.lineup for team one’s lineup.
Inputs, assets, user expressions, schemas, settings
Section titled “Inputs, assets, user expressions, schemas, settings”G="themes/$THEME_ID/rive-graphics/$GRAPHIC_ID"api PATCH "$G/inputs/$INPUT_ID" --data '{"expression":"!$v.hide.value"}'api PATCH "$G/assets/crest.png" --data '{"expression":"$d.1.logo.url"}'api PUT "$G/assets/crest.png/exposure" --data '{"name":"Crest","required":true,"entityType":"team"}'api POST "$G/user-expressions" --data '{"name":"leader","expression":"$d.1.score > $d.2.score ? 1 : 2"}'api PUT "$G/schemas/tennisRankings"api PATCH "$G/settings" --data '{"renderer":"canvas","scale":0.5,"name":"Scorebug","sports":["football"]}'Graphic lifecycle
Section titled “Graphic lifecycle”api GET "themes/$THEME_ID/rive-graphics"api POST "$G/duplicate" --data '{"name":"Scorebug copy"}'api DELETE "$G"Delete is refused with 409 TARGET_NOT_EMPTY while the active theme version pins a published version of the graphic.
Publish, theme snapshots and activation are unchanged; read Import through REST step 6.