A dedicated Model account
If Model Connect is enabled for your account, use its setup screen to explicitly convert a dedicated account to Model. The first release supports one Model account per operator and NFL Weekly Picks in straight and spread formats. Existing Person history stays preserved; model output cannot replace those earlier picks.
Conversion makes ordinary manual pick editing and new entries in other Games unavailable. Disconnecting publishers revokes their access; this account remains a Model and its accepted history keeps its original attribution.
Models compete in separate, models-only exhibition standings. Crews must opt in to include Models. A Model badge identifies the account; it does not verify the quality of a prediction. Publication follows the same fixture locks and scoring rules as the supported Game.
Copy the API base and create a competition-scoped credential in Rivory. Keep it private and revoke it when access changes. These publishers use HTTP; no MCP server is required.
Choose where your model runs
Google Sheets can use the menu below. Excel can export computed UTF-8 CSV values. Python, R, notebooks, hosted workers and AI tools can produce the same output table or HTTP payload. Neither publisher opens your workbook, runs an AI prompt or fetches a model website.
Review the files before using a credential. The Node publisher needs
publish.mjs and client-core.cjs together in one folder, with
Node 22. Google Sheets needs Code.gs, that same shared client and the
manifest. The samples have no third-party dependencies and publish only after explicit
confirmation.
Set up a Google Sheets menu
-
In a private sheet, open Extensions → Apps Script. Paste
Code.gsinto the Code script file. -
Add a script file named ClientCore and paste the entire
client-core.cjsinto it. Enable the manifest in project settings and replaceappsscript.jsonwith the downloaded manifest. Save and reload the sheet. - Open the Rivory Model Connect menu and choose Configure my credential. Enter the API base copied from Rivory, your scoped credential, then choose a competition UUID from the catalog shown by the script and enter your model version. Authorize Google’s requested permissions on first use.
-
List competitions, then Load blank output template.
Choose
straightorspread, then copy an exact canonical round label from the catalog shown by the prompt, such asweek-6. The prompt lists each round’s unlocked fixture count. This replaces only the dedicated Rivory Output tab. - Fill explicit selections, then choose Preview output values. Read every row in Rivory Receipt. Choose Publish reviewed batch / retry only after review.
Keep credentials out of cells
The menu stores your credential in your UserProperties. Spreadsheet or script editors can change the bound code; running their changed code could expose your credential. Use trusted editors or keep this publisher in a separate private sheet. Never paste a key into a cell, chat, formula, source file or log.
Opening, editing or recalculating the sheet does not publish. Avoid automatic Publish triggers. The script reads computed values, freezes the Preview and leaves other model tabs untouched. Later sheet edits do not change the saved batch.
Publish CSV output with Node
In the folder containing both downloaded files, set
RIVORY_MODEL_API_BASE to Rivory’s exact HTTPS API base. Supply
RIVORY_MODEL_TOKEN through a private secret prompt or environment secret
store. Keep real tokens out of command arguments and shell history.
Run these commands, replacing COMPETITION_UUID with an eligible ID returned
by the catalog. The read-only rounds command lists canonical round labels
and unlocked fixture counts; copy one exact label into --round-label:
node publish.mjs competitions
node publish.mjs rounds --competition-id COMPETITION_UUID
node publish.mjs template --competition-id COMPETITION_UUID --format straight --round-label week-6 --out output.csv
Populate the template’s picked_participant_id with the canonical
home_participant_id or away_participant_id on that row. Save
computed values as UTF-8 CSV. Keep expected revisions intact. Blank selections are
skipped; projections never choose a side for you.
node publish.mjs preview --competition-id COMPETITION_UUID --model-version my-model-v1 --csv output.csv --out reviewed-run.json
node publish.mjs publish --run reviewed-run.json --confirm
node publish.mjs receipt --run reviewed-run.json
The private run file preserves the exact payload, run ID, UTC generation time and idempotency key. Preview refuses to overwrite an existing file. A rejected Preview cannot be published. Both publishers limit batches to 100 rows and 256 KiB, and reject duplicate selections or invalid canonical IDs.
Spread picks need kickoff-line consent
The current spread can change before kickoff, including after publication.
expected_line_revision checks the current line used by Preview against
Publish; it does not pin the final grading line. Grading uses the line captured at
kickoff. Your chosen side stays fixed, with no silent recalculation from projections.
For Node spread output, choose --format spread when creating the template.
Publish requires --confirm --accept-kickoff-line. The Sheets confirmation
explains the same rule. An optional source line records context without overriding
Rivory’s grading line.
Keep the receipt, even when a request times out
If Publish times out or a receipt cannot be saved, the server may already have accepted the batch. Keep the saved run. Explicitly retry the same Publish command or Sheets menu action; it sends identical payload bytes, run ID, generation time and idempotency key to recover the owned receipt. Never invent a new key or run as a timeout workaround.
A successful HTTP response can still contain rejected rows. If a fixture locks, a line changes or a pick revision changes after Preview, some rows may be accepted and others rejected. Inspect every receipt before preparing corrections against a fresh catalog. Preserve accepted picks and only change the intended rows. Earlier Person picks remain protected.
An invalid or expired credential needs a deliberate replacement in Rivory. A rate limit requires waiting for the server’s retry interval (currently 60 seconds). Neither sample automatically retries or publishes. If there is no returned batch ID, repeat Publish on the same saved run to recover it.