API reference

Schema index

Generated names, required fields, and schema descriptions; use raw OpenAPI for complete JSON Schema.

Schema index

  • AccessLevel — required: none

    read (Read only) < propose < manage. Propose reads, contributes (media, notes, comments, support, feedback, screenshots, ad drafts) and turns playlist and screen changes into reviews (docs/reviews.md).

  • AccessLimitedBy — required: none

    Why effective_access is lower than the credential's access. project - the project requires review for agent changes. person - the agent's responsible person is a member who cannot approve reviews.

  • AdslotPageWrite — required: id, type, adslot_id

    Whole-page advertising slot. At most 16 adslot pages, and at least one ordinary page with no visibility, are server checks and are not expressed here.

  • AdvertisingAvailability — required: estimated_plays, booked_plays, available_plays, screens, observed_from, observed_to, flight_start, flight_end

    An estimate: the slot occurrences the targeted screens produced over the observed window, projected over the flight, less the plays other direct goals still need on the same screens.

  • AdvertisingAvailabilityQuery — required: flight_start, flight_end
  • AdvertisingCampaign — required: id, revision, name, state, pause_reasons, price_change_pending, daily_cap_mcr, lifetime_cap_mcr, reserved_mcr, spent_mcr, flight_start, flight_end, networks, created_at, updated_at
  • AdvertisingCampaignDraft — required: name, daily_cap_mcr, lifetime_cap_mcr, flight_start, flight_end, networks
  • AdvertisingCampaignList — required: campaigns
  • AdvertisingCampaignNetwork — required: seller_project_id, membership_id, admission_generation, screen_ids, slot_ids, creative_ids, network_cap_mcr, network_reserved_mcr, network_spent_mcr, accepted_pricing_generation, price_change_pending, barrier_generation, enabled
  • AdvertisingCampaignNetworkDraft — required: seller_project_id, screen_ids, slot_ids, creative_ids
  • AdvertisingCategory — required: none

    The advertiser category. Two ads of one category never play in the same ad break on a screen; an ad without a category is never separated.

  • AdvertisingCreative — required: id, revision, media_id, media_revision, sha256, kind, content_type, duration_ms, width, height, bytes, state, created_at
  • AdvertisingCreativeCreate — required: media_id
  • AdvertisingCreativeList — required: creatives
  • AdvertisingCreativeReview — required: id, seller_project_id, creative_revision, state, created_at
  • AdvertisingDaypart — required: start, end
  • AdvertisingDeliveryReport — required: gross_mcr, fee_mcr, net_mcr, completed, interrupted, unbillable, rows, coverage
  • AdvertisingDeliveryRow — required: screen_id, slot_id, reservation_id, gross_mcr, fee_mcr, net_mcr, completed_at
  • AdvertisingDirectCampaign — required: id, revision, name, advertiser, state, flight_start, flight_end, reserved_plays, delivered_plays, media_ids, image_duration_ms, screen_ids, slot_ids, venue_types, cities, tags, dayparts, overbooked, pace, created_at, updated_at
  • AdvertisingDirectCampaignDraft — required: name, advertiser, flight_start, flight_end, media_ids

    A direct campaign: the seller's own deal for an outside advertiser on the seller's own ad inventory. It moves no money.

  • AdvertisingDirectCampaignList — required: direct_campaigns
  • AdvertisingDirectPace — required: status, expected_plays

    Delivery against the goal, which accrues evenly over the flight.

  • AdvertisingDirectPrice — required: model, amount, currency

    The deal price the seller recorded. screenRIG never charges it; it values the report.

  • AdvertisingDirectReport — required: campaign_id, name, advertiser, from, to, delivered_plays, reserved_plays, pace, plays, played_ms, not_played, rows
  • AdvertisingDirectReportRow — required: day, screen_id, slot_id, media_id, plays, played_ms
  • AdvertisingDirectValue — required: model, amount, currency

    The recorded price applied to the delivered plays: per thousand plays for cpm, the whole fee for flat.

  • AdvertisingFillStats — required: from, to, occurrences, direct, marketplace, vast, unfilled, fill_rate, unfilled_reasons, days

    The seller's ad slot supply for all UTC hours overlapping the requested window: occurrences asked for, fills by source, and the unfilled occurrences with the reason of the first ask. The request is at most 35 days; the effective bounds can span up to 35 days plus one hour.

  • AdvertisingFillStatsDay — required: day, occurrences, direct, marketplace, vast, unfilled, fill_rate
  • AdvertisingInventory — required: screen_id, revision, ads_enabled, audience_tags, rate_override_mcr_per_15s, rate_revision, created_at, updated_at
  • AdvertisingInventoryList — required: inventory
  • AdvertisingInventoryWrite — required: ads_enabled
  • AdvertisingJoinedInventory — required: inventory, slots
  • AdvertisingJoinedNetwork — required: seller_project_id, membership_id, policy, admission_generation, scope, price_change_pending, default_rate_mcr_per_15s
  • AdvertisingJoinedNetworkList — required: networks
  • AdvertisingMembership — required: id, seller_project_id, admission_generation, policy_revision, policy, scope, state, revision, created_at, updated_at
  • AdvertisingMembershipList — required: memberships
  • AdvertisingMembershipScope — required: policy, screen_ids, slot_ids
  • AdvertisingNetwork — required: id, revision, enabled, rate_revision, pricing_generation, seller_fee_bps, seller_fee_revision, created_at, updated_at
  • AdvertisingNetworkCreate — required: name
  • AdvertisingQuote — required: id, campaign_id, campaign_revision, revision, state, expires_at, items, pricing_generations, created_at
  • AdvertisingQuoteAccept — required: quote_id
  • AdvertisingQuoteItem — required: seller_project_id, screen_id, slot_id, creative_id, duration_ms, rate_mcr_per_15s, play_price_mcr, pricing_generation, fee_bps, fee_revision
  • AdvertisingRate — required: rate_mcr_per_15s
  • AdvertisingReportCoverage — required: mode, outcomes_complete

    Coverage of playback outcome counts. Monetary totals always come from immutable settlements. When outcomes_complete is false, counts are observed lower bounds and missing history is unavailable, not zero.

  • AdvertisingReview — required: id, creative_id, creative_revision, state, created_at
  • AdvertisingReviewDetail — required: review, creative
  • AdvertisingReviewList — required: reviews
  • AdvertisingReviewRejection — required: reason
  • AdvertisingScope — required: screen_ids, slot_ids
  • AdvertisingSellerCampaign — required: id, buyer_project_id, name, state, flight_start, flight_end, screen_ids, slot_ids, creative_ids, review_state, enabled, price_change_pending, updated_at

    A submitted buyer campaign projected onto the calling seller's network alone.

  • AdvertisingSellerCampaignDelivery — required: completed, reserved_mcr, gross_mcr, fee_mcr, net_mcr

    Lifetime settled plays and amounts on the calling seller's network, plus its current held amount.

  • AdvertisingSellerCampaignDetail — required: campaign, delivery
  • AdvertisingSellerCampaignList — required: campaigns
  • AdvertisingSlot — required: id, revision, name, enabled, accepted_media, max_image_duration_ms, max_video_duration_ms, muted, rate_override_mcr_per_15s, rate_revision, created_at, updated_at
  • AdvertisingSlotList — required: slots
  • AdvertisingSlotWrite — required: name, accepted_media, max_image_duration_ms, max_video_duration_ms
  • AdvertisingSpendReport — required: campaign_id, spent_mcr, reserved_mcr, completed, unbillable, pending, coverage
  • Agent — required: id, name, agent_type, capabilities, state, authenticated_requests, metered_credits, created_at
  • AgentCapability — required: none

    One agent-credential capability area. Capabilities are fixed when the credential is minted; to change them, connect a new agent and disconnect the old one. Canonical order is this enum order; capability lists never contain duplicates.

  • AgentConnection — required: connection_id, name, agent_type, status, capabilities, expires_at, created_at
  • AgentDisconnectRequest — required: none
  • AgentInput — required: none
  • AgentList — required: items
  • AgentScreenScopeUpdate — required: screen_scope
  • AgentSelfStatus — required: agent, connection_ready
  • Alert — required: id, screen_id, condition, state, since, muted, attention

    One screen condition while it lasts. Readers treat an unknown condition as a condition they cannot name.

  • AlertAcknowledge — required: none
  • AlertActor — required: kind, id
  • AlertList — required: items, next_cursor, counts
  • AlertMute — required: id, screen_ids, tags, until, created_at
  • AlertMuteList — required: items
  • AlertMuteWrite — required: until

    At least one screen id or tag.

  • AppStoreNotificationAcknowledgement — required: acknowledged
  • AppStoreNotificationRequest — required: signedPayload
  • AppStoreOffer — required: account_token, products, education_eligible, education_eligibility_source, can_purchase, current_plan_id, subscription
  • AppStoreProduct — required: product_id, plan_id
  • AppStoreSubscription — required: organization_id, plan_id, product_id, original_transaction_id, environment, expires_at, auto_renews, status

    An organization's App Store subscription.

  • AppStoreTransactionRequest — required: signed_transaction
  • Application — required: id, name, revision, created_at, updated_at
  • ApplicationEventContext — required: primitive_id, code
  • ApplicationEventReport — required: severity, code, context
  • ApplicationList — required: items
  • ApplicationPlacement — required: playlist_id, playlist_name, page_id, primitive_id, release_id, release, controller, rect, canvas, screen_count

    One application primitive on one page of one playlist.

  • ApplicationRename — required: name
  • ApplicationUploadCommit — required: sha256, compressed_bytes

    Names the declared archive again; a commit naming other bytes is refused with invalid_request.

  • ApplicationUploadDeclaration — required: sha256, compressed_bytes, expanded_bytes, file_count

    Declares one CLI-produced tar.gz, with the metadata a streamed upload sends as headers.

  • ApplicationUploadSession — required: id, application_id, release_id, operation, upload_url, method, headers, expires_at
  • ApplicationUsage — required: placements, screens
  • ArchivedProjectDevice — required: screen_id, label, host
  • AuditActor — required: kind
  • AuditActorKind — required: none
  • AuditClient — required: kind
  • AuditEntry — required: id, scope, at, actor, source, action, resource, changes
  • AuditFieldChange — required: path, before, after
  • AuditHead — required: scope, seq, hash, floor_seq, floor_hash, unsealed, format
  • AuditList — required: items, next_cursor
  • AuditProblem — required: seq, code, detail
  • AuditResource — required: type
  • AuditRevision — required: type
  • AuditSource — required: none

    The surface a change came through: a dashboard session, the HTTP API, the screenrig CLI, an MCP tool call, a staff member under a write lease, a signed device call, an inbound webhook, or the server itself (a worker applying an approved change).

  • AuditVerifyResult — required: ok, scope, checked, head, problems
  • AutoTopUpDisabledSettings — required: enabled

    Disabling preserves saved amounts and monthly spend. Optional amount fields are ignored, including unfinished drafts.

  • AutoTopUpEnabledSettings — required: enabled, threshold_cents, amount_cents, monthly_limit_cents
  • AutoTopUpSettings — required: none
  • AutoTopUpView — required: enabled, threshold_cents, amount_cents, monthly_limit_cents, paused, this_month_cents
  • BIBrowse — required: items, next_cursor

    Grafana: dashboards (uid, title, folder, tags), or with dashboard set that dashboard's panels (id, title, type) and the dashboard itself. Power BI: workspaces (id, name), or with workspace set that workspace's reports (id, name, embed_url) and the workspace itself. Tableau: views (path as Workbook/View, name).

  • BICheck — required: name, ok
  • BIConnection — required: id, project_id, kind, name, config, embed_origin, secret, last_test, revision, created_at, updated_at

    A project's access to one BI system. Every connection belongs to one project.

  • BIConnectionConfig — required: none
  • BIConnectionList — required: items, next_cursor
  • BIConnectionPatch — required: none
  • BIConnectionWrite — required: name, kind, config
  • BISecret — required: set, hint

    How a stored secret shows. The secret itself is never returned.

  • BITarget — required: none

    What a view shows. Grafana with a connection: dashboard_uid (and optionally one panel). Power BI with a connection: workspace_id and report_id, with pages or rotate_all_pages. Tableau with a connection: view (Workbook/View), with rotate_sheets. Web with a connection: url. Without a connection: only public_url (and rotate_sheets for Tableau).

  • BITestReport — required: at, ok, checks
  • BIView — required: id, project_id, kind, name, target, refresh_s, rotate_s, fit, revision, status, embed_url, created_at, updated_at
  • BIViewError — required: at, code, detail
  • BIViewList — required: items, next_cursor
  • BIViewPatch — required: none
  • BIViewStatus — required: last_ok_at, last_error

    How the view last fared on glass. It changes only when the outcome changes.

  • BIViewTest — required: at, ok, checks
  • BIViewWrite — required: name

    Set connection_id with exactly one of url and target (for Tableau, url may come with a target that holds only rotate_sheets; a web view takes url and no target), or kind (grafana, powerbi or tableau) with target.public_url alone.

  • BIWebCookie — required: name, value, domain

    One cookie of a jar exported from a signed-in browser.

  • BIWebSession — required: state, cookies, cookies_updated_at, last_login_at, login_failures, retry_at

    A web connection's cookies and sign-in. state: idle (nothing yet; the first capture signs in), active, login_needed (the page showed its sign-in page; the next capture signs in), paused (a sign-in did not succeed; the next waits until retry_at), stopped (five refused sign-ins in a row; change the credentials) or expired (a connection with cookies alone whose cookies stopped working; give it a new jar).

  • BIWebStep — required: action

    One step of a scripted sign-in. goto: url (https, public). fill: selector and value. click and wait_for: selector. press: value, a key name such as Enter or Tab, and optionally selector to focus first. wait_ms: ms.

    A value may hold {{username}}, {{password}} and {{otp}}, which the renderer fills from the sign-in; put no password or code in a value, only the placeholder.

  • BillingBalance — required: wallet_revision, remaining_mcr, reserved_mcr, available_mcr, sources, withdrawal
  • BillingPayer — required: kind, id
  • BillingPaymentMethod — required: brand, last4, exp_month, exp_year
  • BillingPayoutStatus — required: rails_available, unavailable_reason
  • BillingPlanSubscription — required: subscription_id, plan, status, entitlement, cancel_at_period_end
  • BillingPortalSession — required: url
  • BillingSourceBucket — required: remaining_mcr, reserved_mcr
  • BillingSources — required: nonredeemable, purchased, ad_earned
  • BillingStatement — required: entries, next_cursor
  • BillingStatementEntry — required: sequence, journal_id, kind, amount_mcr, amount_credits, amount_usd, occurred_at
  • BillingUsageAllowance — required: storage_bytes, api_events, storage_mcr_per_gb_month

    What one payer gets free, as canonical decimal strings. Bandwidth is never charged, so it has no allowance.

  • BillingUsageAmounts — required: bandwidth_bytes, storage_mcr, api_events
  • BillingWithdrawal — required: eligible_earned_mcr, amount_usd_cents, threshold_exclusive_usd_cents, allowed, blockers, rails_available
  • BrowserLinkClaim — required: session_id, status, screen
  • BrowserLinkClaimRequest — required: code
  • BrowserLinkClaimScreen — required: id, public_id, state, public_url
  • BrowserLinkEvent — required: session_id, status, event_id, expires_at
  • BrowserLinkSession — required: session_id, code, display_code, status, expires_at
  • BrowserLinkStatus — required: session_id, code, display_code, status, continuation_path, expires_at
  • BrowserProvisioningCompletion — required: screen, public_url
  • BrowserProvisioningExchange — required: provisioning_token, exchange_id
  • CLIEnrollment — required: project, agent, connection_ready, token, issuance_id, issuance_expires_at, invitation
  • CLIEnrollmentOAuth — required: project, agent, connection_ready, issuance_id, issuance_expires_at, invitation, access_token, token_type, expires_in, refresh_token, refresh_expires_at, scope

    Enrollment in the oauth credential format. The enrollment's grant (client screenrig-cli, Manage on the new project with every capability, identity access Manage) issued its first token pair; an exact retry before issuance_expires_at returns the same pair, later retries return credential_issuance_expired.

  • CLIEnrollmentRequest — required: client_id
  • Campaign — required: id, name, playlist_id, audience, priority, paused, reserved, revision, created_at, updated_at

    A content campaign: every screen in audience shows playlist_id while from, until and windows hold in the screen's timezone. Absent from, until and windows mean always.

  • CampaignAudience — required: none

    Which screens a campaign targets: exactly one of all (every rule matches), any (at least one matches), tag (the screen carries the tag), screen_id (that screen) or folder (the screens in that screen folder and every folder inside it, GET /api/screen-folders; the folder must exist).

    Rules nest at most 3 deep and an audience has at most 500 rules. {"all": []} is every screen of the project; elsewhere all and any list at least one rule.

  • CampaignList — required: items
  • CampaignPatch — required: none
  • CampaignPreviewRequest — required: body
  • CampaignPromote — required: revision
  • CampaignReach — required: published, current, at, empty_groups

    How many active screens the audience matches; a pairing screen is not counted.

    It counts audience matches, not where the campaign plays: an active screen without a default playlist matches and plays nothing. published is the count when the campaign was last published (created, or updated with a different audience, playlist_id or paused); current the latest count.

    A change to an active screen's tags, folder or state, or a folder move, recounts the campaigns whose audience names what changed about 15 seconds after the changes stop and appends campaign.reach_changed (published, previous, current; republished true from a publish) and, per tag or folder of the audience that starts or stops matching screens, campaign.group_changed (kind, value, matched); a publish that drops an empty tag or folder from the audience appends campaign.group_changed with removed true and matched 0.

    Absent on a campaign not published or recounted since reach was introduced.

  • CampaignRevision — required: revision, created_at, change, current, campaign

    One stored revision of a campaign: the campaign as it was after a write. change says what made it: created, edited (an update or a schedule import), restored or promoted (a copy of an earlier revision, named by restored_from), or baseline (the revision the campaign held when its history began, before any write recorded one).

    A value this reader does not know reads as edited.

  • CampaignRevisionList — required: items
  • CampaignScreens — required: campaign_id, counts, items
  • CampaignStatus — required: campaign_id, screen_id, status

    One campaign's standing on one screen.

    On a screen whose Player resolves its own stack (schedule.stack) and receives it, a campaign that holds by time stands where that stack puts it: a strip or main campaign plays in its region and a display lock on its displays; one the stack does not carry is pending or blocked (playlist_unavailable). playing: the screen shows it. pending: it should show and the switch lands within a minute. waiting: outside from, until or windows now (next_start, when it starts within eight days). ended: until has passed. outranked: it holds, but a screen takeover (reason takeover) or another campaign (reason campaign, by) wins. conditional: it holds by time and plays while what only the Player observes holds too (reason interaction: someone is using the screen; data: its data condition). paused. blocked: it cannot show here (reason no_default_playlist, no_timezone, or playlist_unavailable: the playlist is missing, unapproved or does not fit the screen, region_not_laid_out: it is laid out on no display of this screen (its strip fits none of the displays it targets, or its display lock names none of the screen's outputs) and is left out of this screen's stack, or stack_only: the screen's Player does not resolve its own stack, and only one that does honors a region, a display lock, interaction or a data condition). not_in_audience.

  • CampaignWrite — required: name, playlist_id, audience
  • CanvasBackground — required: none

    Solid canonical uppercase #RRGGBBAA, or a top-to-bottom linear gradient.

  • CanvasColor — required: none

    Canonical uppercase sRGB RRGGBBAA.

  • CapPull — required: none

    CAP sources the platform reads for the trigger, with where the target screens are and which alerts count: the params of a cap-alert card placement (docs/feeds.md "CAP alerts"). Each source URL is fetched once per minute for every trigger and placement that names it.

    With no sources the platform's public feeds covering location are read (NWS, Canada NAAD, and MeteoAlarm for a location with area codes). The most severe matching alert takes the target screens over exactly as a pushed message would; when the sources show none (a cancel or an expiry) a pulled alert ends.

    A stale or failing source never ends an alert. location is required unless sources are given.

  • Capabilities — required: api_version, protocol_version, application_compressed_bytes, application_expanded_bytes, application_package_bytes, application_file_count, application_file_bytes, application_path_depth, application_path_bytes, media_image_bytes, media_audio_bytes, media_video_bytes, playlist_max_pages, playlist_max_items_per_page, playlist_max_media_per_selector, transition_max_duration_ms, screens_per_project, project_content_bytes, founding_period_ends_at, features
  • CardCatalogue — required: cards
  • CardCreate — required: type, params
  • CardDataEntry — required: key, document, bytes, sha256, revision, created_at, updated_at
  • CardDataList — required: items, next_cursor
  • CardDataSummary — required: key, bytes, sha256, revision, created_at, updated_at
  • CardDataWrite — required: document
  • CardDetails — required: id, major, version, params_schema, data_schema, feed, tier, layouts, example
  • CardFile — required: src, sha256
  • CardInstance — required: id, project_id, type, major, params, created_at, updated_at, revision
  • CardKVWebhook — required: id, card_id, description, mapping, enabled, signing, url, created_at, updated_at

    An incoming webhook that writes a card's data document.

  • CardKVWebhookCreate — required: none
  • CardKVWebhookList — required: items
  • CardKVWebhookRotate — required: none
  • CardKVWebhookUpdate — required: none
  • CardKVWebhookWithSecrets — required: none
  • CardKVWebhookWriteResult — required: status
  • CardRequirements — required: cardml, features
  • CardSummary — required: id, title, short, category, tags, tier, layouts, majors
  • Comments — required: comments
  • CommentsWrite — required: comments
  • Connection — required: id, project_id, provider, mode, name, status, last_error, config, secret, last_test, revision, created_at, updated_at

    A project's reusable access to Microsoft or Google. Sources, Power BI connections and SharePoint media sync accounts name one in config.connection_id instead of carrying credentials of their own.

  • ConnectionCheck — required: name, ok, detail
  • ConnectionConfig — required: none

    What a connection names besides its secret; only the members its provider and mode use are present. A secret, a key or a refresh token is never here.

  • ConnectionConfigWrite — required: none

    Microsoft, mode own_app: both members. Not accepted for a Google connection or for mode screenrig_app.

  • ConnectionConsent — required: none

    A connection answered with its one-time consent link, which only a write that makes one carries: creating a connection in mode screenrig_app and POST /api/connections/{id}/connect. The person who consents opens consent_url before consent_expires_at. It is the link of one consent: send it to that person only. A read of the connection never carries it.

  • ConnectionError — required: code, message, at

    Why a connection is not working. The message is a fixed sentence plus, for Microsoft, the AADSTS code; it never repeats text a caller sent.

  • ConnectionList — required: items, next_cursor
  • ConnectionPatch — required: none
  • ConnectionSecret — required: set, hint

    How an answer shows a connection's secret, key or refresh token. The value is never returned.

  • ConnectionTest — required: at, ok, checks
  • ConnectionWrite — required: provider, mode, name
  • CreatedProject — required: project, organization
  • CreditPurchase — required: id, status, amount_cents, credits, credited
  • DashboardAgentAction — required: project_id
  • DashboardApplicationPreviewLaunch — required: release_id, launch_url, expires_at
  • DashboardApplicationSummary — required: count
  • DashboardBalance — required: credit_remaining, credit_included, credit_reset
  • DashboardBoot — required: none

    One request for the dashboard shell. Each member is the body the named route answers for this same session, and is absent when that route would not answer 2xx for it. advertising_network is null when the project has no network.

  • DashboardDisplayName — required: none

    Trimmed printable display name, at most 80 UTF-8 bytes. Rejects controls, URL-looking text, @, www., ://, and credential material. Never authorization.

  • DashboardEmail — required: email, email_verified, email_revision

    The current user's own email view. The verified address stays effective while a change is pending, and the pending candidate is visible only to its owner.

  • DashboardEmailVerificationAccepted — required: status
  • DashboardHealthSummary — required: display_disconnected, hot, crashing, stale

    Active screens with a health report, counted by condition; a screen can count in several. display_disconnected, hot, and crashing count only online screens whose latest report is current (not stale); stale counts online screens whose report is older than 35 minutes and nothing else.

  • DashboardMe — required: user_id, display_name, email, password, passkeys, created_at
  • DashboardMediaSummary — required: count, bytes

    Ready media counters for the session's project. bytes counts stored media bytes only; it is not the project used_bytes total, which also covers release trees and key/value entries. image_bytes, video_bytes and audio_bytes split bytes by primitive and always sum to bytes while image, video and audio are the only primitives; if another primitive is ever stored, the three sum to less than bytes.

  • DashboardMember — required: user_id, display_name, joined_at, passkeys, password, owner, external
  • DashboardMemberList — required: items, viewer_user_id, viewer_is_owner
  • DashboardPasskey — required: id, name, credential_id, provider, created_at, last_used_at
  • DashboardPasskeyAssertion — required: ceremony_id, request_options
  • DashboardPasskeyAssertionComplete — required: ceremony_id, credential
  • DashboardPasskeyComplete — required: ceremony_id, credential
  • DashboardPasskeyList — required: rp_id, user_handle, items
  • DashboardPasskeyPatch — required: name
  • DashboardPasskeyProof — required: type, ceremony_id, credential
  • DashboardPasskeyRegistration — required: ceremony_id, creation_options
  • DashboardPasswordLogin — required: email, password
  • DashboardPasswordProof — required: type, password
  • DashboardPasswordSet — required: password, proof
  • DashboardPendingEmail — required: email, expires_at
  • DashboardProject — required: status, created_at, email, screen_count, screen_limit, used_bytes, reserved_bytes, content_limit_bytes, event_retention_days, name

    Status, contact address, enforced limits, usage, retention, and public whole-credit state for one project. The internal plan identifier remains unpublished.

  • DashboardProjectList — required: items
  • DashboardProjectListItem — required: id, name, last_used_at
  • DashboardProjectReference — required: id, name
  • DashboardProjectSwitch — required: project_id
  • DashboardProof — required: none
  • DashboardProofRequest — required: proof
  • DashboardReauthentication — required: ceremony_id, options
  • DashboardReauthenticationRequest — required: kind
  • DashboardSSOProof — required: type

    Proof by a recent single sign-on. It is valid while the current session signed in through the organization's identity provider at most 10 minutes ago, and carries no ceremony and no secret. Otherwise the route answers reauthentication_required, and the person signs in through their provider again (POST /api/session/sso-starts, intent reauth).

  • DashboardScreenSummary — required: total, online, pairing_pending, active, archived

    Screen counters for the session's project. total is pairing_pending plus active and excludes archived, matching project screen_count. online is derived from live paired runtime event streams exactly as Screen.online is; it is not a stored boolean and not a player heartbeat.

  • DashboardSession — required: user_id, display_name, email, project, auth_method, authenticated_at, expires_at, dev_auth, staff, shadow, passkey_enrollment_required, email_verification_required

    Person session. Identifiers are descriptive; the session cookie establishes authority. A person with no projects has project: null.

  • DashboardSessionOrganization — required: id, name, managed

    The person's home organization.

  • DashboardSessionSSO — required: organization_id, provider_name, linked

    The person's single sign-on context. Present whenever the person's verified address is at a domain whose organization has an identity-provider connection; linked is false until the person signs in through it or links it. An SSO session lasts 24 hours from sign-in and is not extended by use.

  • DashboardStaffWriteMode — required: request_id, project_id, expires_at
  • DashboardSummary — required: screens, media, applications
  • DeletedProject — required: id, screens, paired_screens_active, paired_screens_archived, paired_screens_completed_pending, agents, media, applications, playlists, memberships
  • DemoRequestInput — required: email, country, screen_range, organization, budget, timezone, source, flow_id
  • DemoResult — required: route, booking, review_requested, video_url, email, country, timezone, flow_id, source
  • DemoSlots — required: slots, timezone
  • DemoSource — required: none
  • DeviceSessionRequest — required: none

    Cookie-paired browser mint. The body is optional. Unknown members are ignored (docs/player-compatibility.md §1.1).

  • DisplayWindow — required: days
  • DocsPage — required: url, title, markdown, truncated, sections, corpus_commit
  • DocsSearchResponse — required: results, corpus_commit
  • DocsSearchResult — required: url, title, section, snippet, score
  • EducationEligibilitySource — required: none

    Who decided education_eligible. staff is a staff decision, either way, and is final. school_email is the automatic decision from an admin's verified K-12 school email address (a school domain such as k12.ca.us or sch.uk; never a general education domain such as .edu or .ac.uk). The empty string means nobody decided.

  • EmailVerifyRequest — required: token
  • EmailVerifyResult — required: purpose, status
  • EmptyPaymentRequest — required: none
  • EnrollmentInvitation — required: id, status, expires_at
  • Event — required: cursor, type, severity, message, at
  • EventActor — required: user_id, display_name

    Dashboard user that caused this mutation. Optional and absent on every event an agent, the CLI, a player, or a worker produced, so the field distinguishes a dashboard mutation rather than labelling all traffic. It is descriptive attribution only and is never authorization. display_name is the name the user chose at registration and is not verified.

  • EventAgent — required: agent_id, name, agent_type

    Safe agent principal attribution present only when the event was directly caused by an authenticated agent bearer. It is never authorization.

  • EventCommand — required: name, method

    The agent request that caused this event. Optional and absent on every event a dashboard user, a player, or a worker produced. It is descriptive attribution only and is never authorization. Every field is written by the server from the route it matched or from the problem registry.

    A command object cannot carry an argument vector, a request body, a header, or any text the caller chose, and there is deliberately no field for one. name and method appear on every event an agent request committed.

    The outcome fields appear ONLY on an agent.command event, which is the record for a request that committed no domain event: a committed domain event is itself the proof that the request succeeded.

  • EventList — required: items, next_cursor
  • FeedDocument — required: schema, fetchedAt, attribution
  • FeedPending — required: key, state, retry_after_seconds
  • FeedbackContext — required: none

    Closed diagnostic envelope. Every member is an optional constrained scalar, nesting is structurally impossible, and an unknown member is rejected with invalid_request. The shape exists so a client cannot persist argument values, credentials, or free-form environment data through it.

  • FeedbackList — required: items
  • FeedbackReplyWrite — required: text
  • FeedbackResponse — required: id, text, status, created_at

    One immutable staff or agent reply. An absent author identifies a staff reply. Plain text (escape it for any display context); credential-shaped text is replaced with [redacted] before it is stored.

  • FeedbackStatus — required: none

    Where staff stand on a submission. waiting_on_user asks the submitting agent for information; an agent reply reopens it or a closed report. A "planned" report keeps its status.

  • FeedbackSubmission — required: id, kind, title, body, created_at

    One project-scoped submission. Its own fields (id, kind, title, body, context, created_at) never change after it is written. status is open until staff respond and then the status of the latest response; agent replies reopen reports awaiting input or closed, while a "planned" report keeps its status.

    Responses are staff and agent replies, oldest first and at most 20, never edited or removed. Each reply also appends a feedback.responded event to the project's event stream (resource.id is the submission id; details carry response_id, status, fixed_in and author for agent replies, never the text).

    The submission id is never authorization: only the owning project reads it.

  • FeedbackWrite — required: title, body
  • FleetLinkPatch — required: none
  • FleetLinkWrite — required: label
  • GroupBinding — required: binding_id, group_id, group_name, role, created_at
  • GroupBindingCreate — required: group_id, role
  • GroupBindingGroup — required: id, display_name, member_count
  • GroupBindingList — required: bindings, groups
  • HLSStreamSource — required: protocol, url
  • HealthResponse — required: status
  • HealthTrend — required: items, next_cursor
  • HealthTrendHour — required: hour, screens_reporting, hot, display_disconnected, crashing
  • HostContext — required: platform

    The shell and hardware a player runs on, as the player reported it. A HINT that names a device; never a credential, never authorization. Only the Ed25519 key authorizes.

    Stored per screen, replaced by every session mint that carries one, deleted with the screen, never written to operation logs, never echoed in problem responses, and never returned to any project other than the owner's. Read-only on the project API; ScreenPatch cannot write it.

  • HostDevice — required: none

    Optional hardware identifiers. duid and serial are the only two the recovery hint consults; a failed read on the player omits the field.

  • IceServer — required: urls

    An RTCIceServer. Port 53 URLs are removed because browsers block them and nothing trickles.

  • IdentityProvider — required: connection_id, kind, preset, name, jit, service_provider, ready_to_require, policy, revision, created_at, updated_at

    The organization's single sign-on connection. It holds no secret.

  • IdentityProviderCertificate — required: sha256, subject, not_after
  • IdentityProviderOIDC — required: issuer, client_id, client_secret_set, scopes
  • IdentityProviderOIDCWrite — required: client_id
  • IdentityProviderSAML — required: idp_entity_id, idp_sso_url, certificates
  • IdentityProviderSAMLWrite — required: none
  • IdentityProviderServiceProvider — required: oidc_redirect_uri, saml_entity_id, saml_acs_url, saml_metadata_url

    The values to enter at the identity provider, derived from the dashboard origin and the connection id.

  • IdentityProviderTest — required: at, ok, subject_present

    The outcome of the last test sign-in through the connection.

  • IdentityProviderWrite — required: kind, preset, name, proof
  • Invitation — required: id, kind, delivery, status, project_id, created_at, expires_at
  • InvitationAcceptRequest — required: token, mode

    New credentials are required for create_login and reset. Link create_login requires the verified signup cookie and uses its display name and email.

    Email create_login requires display_name. signed_in needs sign-in within ten minutes or an invitation_accept proof bound to the invitation id. buyer applies only to ad_buyer; new buyer projects start at zero credit.

  • InvitationAccepted — required: kind, project_id, next
  • InvitationAdvertising — required: screen_ids, slot_ids, policy

    Seller-owned scope: at least one screen or slot. Screens only, slots only, or both are accepted.

  • InvitationBuyer — required: none
  • InvitationCreate — required: kind

    Email delivery requires emails. Link delivery is project_member only and omits emails and advertising. ad_buyer requires advertising. At most 50 outstanding member and buyer invitations per organization; an outstanding email invitation of the same kind and address is reused.

  • InvitationCreated — required: invitations
  • InvitationCredential — required: none
  • InvitationEmailVerificationAccepted — required: status, expires_at
  • InvitationEmailVerificationRequest — required: token, display_name, email
  • InvitationInspect — required: id, kind, delivery, project, expires_at, person, modes, methods

    Non-consuming inspection. person is null for links. Never reports signup verification state, except that a sign-in reset, whose link went only to the address, says whether completing it replaces an unverified account (replaces_unverified_account). Email modes are create_login or signed_in; links offer both, and resets offer reset.

  • InvitationInspectRequest — required: token
  • InvitationIssued — required: id, kind, delivery, status, project_id, created_at, expires_at
  • InvitationKind — required: none
  • InvitationList — required: items, next_cursor
  • InvitationPasskeyOptionsRequest — required: token, mode
  • InvitationPasswordCredential — required: type, password
  • InvitationSignup — required: email, display_name, verified, expires_at
  • InvitationStatus — required: none
  • KVEntry — required: application_id, key, value_base64, content_type, bytes, sha256, revision
  • KVList — required: items, next_cursor
  • KVSummary — required: application_id, key, content_type, bytes, sha256, revision
  • KVWebhook — required: id, application_id, key, description, url, created_at

    An incoming key/value webhook. Its secret is returned only by create and rotate-secret.

  • KVWebhookCreate — required: key
  • KVWebhookDelivery — required: at, outcome, status, bytes, request_id
  • KVWebhookDeliveryList — required: items
  • KVWebhookList — required: items
  • KVWebhookWithSecret — required: none
  • KVWebhookWriteResult — required: key, revision, bytes, sha256, content_type, updated_at
  • KVWrite — required: value_base64
  • LevelDate — required: date

    One specific civil date, the whole day or between start and end as a window's. It starts between from and until and is not an exception date.

  • LevelInteraction — required: none

    The level holds while someone is using the screen: from a touch, click or key until idle_s seconds pass with no input. Typical use: an interactive page above an attract loop. idle_s is stored and returned (60 when omitted).

  • LevelMonthly — required: none

    A monthly occurrence in the screen timezone: day (1 to 31; a month without that day skips it), or nth (1 to 4, -1 the last) and weekday. start and end as a window's; the date the occurrence starts owns it.

  • LinearGradientBackground — required: type, stops

    Top-to-bottom linear gradient. There is no angle field. stops has 2 through 8 entries, strictly increasing at in [0, 1], first at=0, last at=1.

  • LinearGradientStop — required: at, color

    One stop on a top-to-bottom linear canvas background. at=0 is the top edge, at=1 is the bottom edge.

  • LiveFrames — required: live_id, state

    Progress of a live session's frame adapter. Open schema.

  • LiveSession — required: state, screen_id, viewer_url

    A screen's live session. Open schema.

  • LiveStartRequest — required: none
  • LiveViewer — required: viewer_id, live_id, offer, ice_servers, expires_at

    A viewer's relay offer. Open schema.

  • LiveViewerAnswer — required: answer
  • ManifestActivatedContext — required: manifest_revision
  • ManifestActivatedReport — required: severity, code, context
  • ManifestUpgradeContext — required: manifest_revision, state
  • ManifestUpgradePlaylist — required: id, name, revision

    The playlist identity behind an issued or queued desired revision: desired_playlist uses its exact desired grant or the read-only shared content goal for the current effective assignment before grant issuance. active_playlist always uses the exact acknowledged historical grant, never a newer assignment or content edit. id plus revision are the playlist version an operator reads as Target v42 / Playing v41; name is the playlist's display name, null when the playlist no longer exists or cannot be resolved.

    A missing historical active grant is null, never a fabricated revision. A queued desired goal grants no content access.

  • ManifestUpgradeReport — required: severity, code, context

    One latest-wins manifest-upgrade lifecycle snapshot for the session screen.

    The server stores one slot per screen and derives the project read model Screen.manifest_upgrade from it; a stale, superseded, or post-activation pre-activation report is accepted with no change (202), never refused as a conflict, and no report ever promotes a grant. severity is envelope-only: the derived project event severity comes from state.

  • McrString — required: none

    Exact integer millicredit amount as a canonical decimal string. 1 credit is 1000 mcr.

  • Media — required: id, filename, primitive, content_type, operation_id, sha256, bytes, revision, state, created_at, updated_at
  • MediaAvailability — required: none

    When dynamic selectors may pick the media, in each screen's time zone: inside [from, until) and on an occurrence of windows, monthly or dates (none of the three: every day) whose date is not in except. The schedule's level grammar without data and interaction.

  • MediaAvailabilityPatch — required: availability
  • MediaCommit — required: content_type, bytes, sha256

    Declares only what the server can re-verify against the stored object byte for byte. Codec identity is not declared here: the server derives it from the container during asynchronous verification, so a client cannot assert a codec that drives player behaviour.

  • MediaFolder — required: id, name, parent_id, revision, created_at, updated_at

    One media library folder. A playlist selector by:folder plays the ready files directly inside it, not those of its subfolders.

  • MediaFolderCreate — required: name
  • MediaFolderList — required: items
  • MediaFolderPatch — required: none
  • MediaGenerationReference — required: none

    Exactly one of media_id or b64. HTTP URLs are rejected.

  • MediaGenerationRequest — required: prompt

    Requests one still image. The prompt is customer bytes and is never returned, logged, or published on project SSE. aspect_ratio defaults to 16:9. quality is low, medium, or high and defaults to medium. tag is stored on the ready media object like an upload tag. Optional references are inline base64 or a project media_id; HTTP URLs are rejected.

    The summed size of all references of one request, inline and media_id alike, must not exceed 25165824 bytes (24 MiB); a request over the bound is refused.

    On Standard, remaining that cannot cover twice the vendor cost of the still, rounded up to whole credits, after the intro floor (negative 1,000,000 credits until 2027-01-01, then zero) returns payment_required, except development. Other plans are never refused for their balance.

  • MediaGenerationUsage — required: quality, credits, usd

    Customer-facing debit for one stored still, the usage in a succeeded media.generate Operation's result. quality is the requested quality and changes the image, not a fixed price. credits are twice the vendor cost of that still, rounded up to whole ScreenRig credits. usd is the dollar equivalent of those credits.

    Never a vendor name, vendor cost, or token count.

  • MediaList — required: items
  • MediaMove — required: folder_id

    At least one id across media_ids and folder_ids, at most 1000 in all.

  • MediaMoveResult — required: media, folders
  • MediaReplace — required: upload_id
  • MediaRestore — required: none
  • MediaRestorePending — required: status, review, warnings
  • MediaRestored — required: media, warnings
  • MediaSelectorTagFilter — required: none
  • MediaSelectorWeights — required: none

    Shares of a weighted selector, keyed by media id or tag:NAME.

    An item's weight is its media id key if present; otherwise the first tag:NAME key, in alphabetical order, among the tags it carries, with that weight split equally among the items of the selection that share the key, so a sponsor's share holds however many creatives it has; otherwise the item is its own group with weight 1.

    Every full cycle plays each item exactly its share.

  • MediaSingleTagPatch — required: tag
  • MediaSync — required: id, project_id, account_id, provider, name, folder_id, every_s, state, source, next_run_at, revision, created_at, updated_at

    One source folder kept in step with one media folder.

  • MediaSyncAccount — required: id, project_id, kind, name, config, secret, state, revision, created_at, updated_at

    What syncs read through: the credentials of the project's own Microsoft Entra app (microsoft365), one person's connection to Canva (canva) or Dropbox (dropbox), or a Google service account that folders are shared with (google_drive). The client secret, the tokens and the key are sealed and never returned.

  • MediaSyncAccountConfig — required: none
  • MediaSyncAccountConnect — required: none

    An account answered with its one-time consent link: what creating a Canva or Dropbox account and media sync account connect answer. The person who owns the Canva or Dropbox account opens authorize_url, signed in to Canva or Dropbox, before authorize_expires_at. It is the link of one consent: send it to that person only. Reads of the account never carry it.

  • MediaSyncAccountList — required: items, next_cursor
  • MediaSyncAccountPatch — required: none
  • MediaSyncAccountWrite — required: kind, name
  • MediaSyncCheck — required: name, ok, detail
  • MediaSyncDesign — required: id, title

    A Canva design the connected person can see.

  • MediaSyncDesignList — required: items, continuation
  • MediaSyncList — required: items, next_cursor
  • MediaSyncPatch — required: none
  • MediaSyncRun — required: at, status, added, updated, removed, pending_delete, skipped_total

    The summary of a sync's latest run.

  • MediaSyncRunError — required: code, detail
  • MediaSyncSecret — required: set, hint

    How an answer shows an account's client secret, a Canva or Dropbox account's tokens (set once connected, with no hint), or a Google Drive account's own service-account key (set when the account has one; hint is the last four characters of its private_key_id). The value is never returned.

  • MediaSyncSkipped — required: name, reason
  • MediaSyncSource — required: web_url

    The source a sync reads, resolved when the sync was created. A SharePoint folder has drive_id and item_id; a Dropbox folder item_id and path; a Google Drive folder item_id, drive_id when it is in a shared drive, and shared_by; a Canva design has design_id and the members after it.

  • MediaSyncTest — required: at, ok, checks
  • MediaSyncWrite — required: provider, account_id
  • MediaTagPatch — required: none
  • MediaTagsPatch — required: tags
  • MediaUploadDeclaration — required: filename, content_type, bytes, sha256

    Declares one upload. The bytes maximum is a plan-independent transport ceiling, not an achievable size. An image content type is bounded further at 20971520 bytes, 20 MiB, and a larger image declaration is rejected with invalid_request before any byte is transferred.

    That image bound is a byte-only gate: declaration never decodes the image to enforce it, and it applies to animated GIF and animated WebP exactly as it applies to a still. The default plan has no product storage cap.

    A custom storage ceiling, when present, is checked first and a declaration it cannot hold is rejected with quota_exceeded before any byte is transferred.

    A Standard project with no credit left is refused declare and commit with payment_required when the bytes its payer stores, with this upload, pass 1000000000 bytes (1 GB, Standard's free storage); bandwidth is never charged.

    An audio/mpeg (MP3) declaration is bounded at 178257920 bytes, 170 MiB, and a larger one is rejected the same way; read media_audio_bytes to preflight it.

    A video/mp4 or video/webm declaration is bounded by the project's plan, 500000000 bytes, 500 MB, on Standard and 1000000000 bytes, 1 GB, on every other plan, and a larger one is rejected the same way, naming the limit that applies; read media_video_bytes from GET /api/project/capabilities to preflight it.

    A plan change affects only later declarations: stored videos keep playing. Read media_image_bytes from the capabilities document to preflight the image bound, and project_content_bytes there, or content_limit_bytes on the project, to know any custom storage ceiling. An optional tag is stored on the ready media object and is not redeclared at commit.

    An optional source_filename records the caller's original file name when the client transcoded the bytes before upload; the ready object's filename is then derived from it so distinct sources never collide (photo.png uploaded as photo.webp is stored as photo.png.webp, photo.jpg as photo.jpg.webp, and a source photo.webp stays photo.webp).

  • MediaUploadSession — required: id, operation, upload_url, method, headers, expires_at
  • MediaUploadSource — required: filename, content_type, sha256, bytes

    Verified original upload identity when ingest normalized EXIF orientation. Read-only; use it to recognize retries. The ready media digest, size and type describe the normalized delivery bytes.

  • MediaUsage — required: playlists, screens
  • MediaUsagePlaylist — required: id, name, uses, screen_count
  • MediaUse — required: kind, where

    One way one playlist holds or reaches the media file; a playlist that does it on several pages is one use.

  • MediaVersion — required: number, current, filename, content_type, sha256, bytes, source, created_at
  • MediaVersionActor — required: kind
  • MediaVersionPage — required: items, next_cursor
  • MediaWarning — required: code, detail, playlists
  • MediaWarningPlaylist — required: id, name
  • MemberActivity — required: id, project_id, user_id, display_name, at, kind, action, outcome, status, source
  • MemberActivityClient — required: kind

    The client as the edge request log names it, parsed from the User-Agent and Sec-CH-UA-Platform.

  • MemberActivityKind — required: none

    sign_in and sign_in_failed carry auth_method; credential_changed is a passkey added, renamed or removed, a password set, or an email change requested or verified; reauthenticated is one checked proof (action reauthentication.<proof kind>); mutation is any other dashboard change.

  • MemberActivityList — required: items, next_cursor, recorded_since
  • MemberActivityOutcome — required: none

    ok below status 400, refused for a 4xx answer, failed for a 5xx one.

  • MemberActivityResource — required: type
  • MemberApproverUpdate — required: can_approve
  • MemberScreenScopeUpdate — required: screen_scope
  • MemberUploadScopeUpdate — required: upload_scope
  • NativeIdentityChallenge — required: nonce, expires_at, aud, op, request_hash

    Compare the returned op and request_hash with your locally computed values before signing. Each nonce expires in 120 seconds and can be consumed once.

  • NativeIdentityChallengeRequest — required: kid, op, request_hash

    Supply the operation and its request_hash for every challenge. An unknown key also requires public_key and op=pairing.start. Creating a challenge does not enroll the key.

  • NativeIdentityProof — required: kid, public_key, signature

    Compact JWS protected header is exactly {"alg":"EdDSA"}. Claims are kid, nonce, aud=screenrig-runtime, op, integer iat/exp, nonempty jti, and request_hash.

    Contextual proofs last at most 120 seconds and expire no later than their issued challenge. request_hash is lowercase SHA-256 hex of UTF-8 strings joined by one NUL, with no trailing NUL, starting with screenrig.native.identity.request.v1 and op.

    Append Idempotency-Key for pairing.start and session.mint; append the exact srp_ pairing credential then completion_nonce for pairing.complete; append nothing for identity.reset. Every proof must include request_hash. A cached operation result still requires a fresh issued proof or the exact accepted proof while its short-lived receipt remains valid.

    Duplicate or unknown JWS/JWK members, noncanonical base64url, and non-prime-order keys are rejected. Unknown request body members are ignored.

  • NativeIdentitySessionRequest — required: kid, public_key, signature

    NativeIdentityProof with op=session.mint plus the optional host hint. A present host REPLACES the host stored on the screen, because firmware and shell versions drift over a screen's life. The hint never affects authorization; only the signed proof does.

    Unknown members are ignored, and host and playback are read tolerantly (docs/player-compatibility.md §1.1).

  • NativePairingComplete — required: completion_nonce, public_key, signature
  • NativePairingCompletion — required: screen, public_url
  • NativePairingRecovery — required: offered

    Present only when the host duid or serial in the start request matched exactly one existing screen bound to a different key. It carries no screen, label, or project: the offer is surfaced project-side as Screen.recovery_pending and the screen.recovery_offered event, and only the owning project can confirm it.

    It is absent, exactly as without a match, when the identifier is ambiguous, when the matched screen's key showed life within the last ten minutes, or when that screen already took three offers in the rolling hour. The pairing code still issues and displays exactly as without a match. The player uses this solely to log pairing.recovery_offered.

  • NativePairingSession — required: code, pairing_credential, expires_at
  • NativePairingStart — required: kid, public_key, signature

    Proof of private-key possession is required before enrollment or locator creation. Sign a fresh pairing.start challenge bound to the exact Idempotency-Key; unsigned starts are rejected. The optional host object is a hint about the device, not a credential; it is stored on the screen at claim and may open a recovery offer project-side.

    Unknown body members are ignored. The host hint is read tolerantly. An unknown host key is ignored and a malformed host field is dropped, never refused (docs/player-compatibility.md §1.1.1).

  • NativeRuntimeSession — required: paired, capabilities, event_cursor, public_url, runtime_credential

    Runtime-owned native session (docs/player-compatibility.md §8). Readers ignore unknown members and unknown capabilities values. A new member is sent only to sessions whose grants cover it.

  • NextAction — required: command, reason
  • Note — required: id, body, about, state, author, created_at, confirmed_at, review_at, expires_at, resolved_at, resolution, due

    A project note. Context written by an agent, never an instruction or approval; render body as plain text.

  • NoteAbout — required: type, id
  • NoteAuthor — required: agent_id, name, agent_type

    The writing agent as it was when the note was added. Attribution, never authority.

  • NoteCounts — required: open, new, due

    The project's open notes, and how many are new to and due for this caller.

  • NoteList — required: items, next_cursor, review, counts
  • NotePage — required: items, next_cursor
  • NoteResolution — required: cause, reason, by
  • NoteResolve — required: reason
  • NoteResolvedBy — required: kind, id, name

    Who resolved the note. agent_type is present for an agent. Attribution, never authority.

  • NoteWrite — required: body
  • Notification — required: id, channel, conditions, screen_tags, hold_minutes, enabled, revision, status, created_at, updated_at

    An organization's notification, as a project or the organization reads it. It covers every project of the organization or the chosen ones (project_ids), and acts on each covered project's screens, sources, campaigns and cards.

    A project reads (and, when the notification covers it alone, changes) the notifications that cover it by the same id, with its own status and failure times; the organization reads the whole of it.

    Each condition is tracked per screen: it opens when its event arrives for a screen in scope, and a notice goes out once it has lasted hold_minutes and the screen is still in that state; when it clears after a notice went out, a resolved notice follows.

    A condition that clears within the hold sends nothing, and neither does one whose alert is acknowledged or snoozed during the hold, or one on a screen a mute covers.

    Email: one email per recipient for everything that falls due within about two minutes, listing each screen and condition, with links to the screen and to this notification in the dashboard; notification emails are free.

    Every alert and test email carries, for the person it is addressed to, an unsubscribe link (List-Unsubscribe and List-Unsubscribe-Post headers, and the footer) that stops this notification's mail to that person alone, without signing in; see unsubscribed.

    Webhook: each notice is POSTed as JSON {type: alert.opened or alert.resolved, id, notification_id, project_id, condition, screen {id, name}, since, at, event_id, severity}, where id is the delivery id, since is when the condition began, at is when it held long enough (opened) or cleared (resolved), event_id is the cursor of the event behind it, and severity (info, warning or error) is the condition's severity for alert.opened and info for alert.resolved, on every webhook notification.

    A campaign's notice also carries reach {published, current} (reach_dropped: the screens the campaign reached when it was published and reaches when the notice is sent) or audience_group {kind: tag or folder, value: the tag or the folder id} (group_empty); email and chat say the same in words.

    A notification that sets min_severity or severity also says it in its email, Slack, Telegram and Teams text.

    Teams and PagerDuty always show the effective severity. alert.resolved for screen_offline also carries likely_cause, the cause of the outage that ended (ScreenOutage.likely_cause) or null when unknown; it waits up to two minutes after the screen comes back for the first health report to decide it, and an email names it too.

    A restart is decided at once; a network or platform cause needs a health report received after the screen is back, which a Player may send up to 15 minutes later, so a notice that went out before then carries null and the cause shows in ScreenOutage.likely_cause and screen.outage_classified.

    Email and the chat channels say three or more screens that fall into one condition within five minutes and share a network, location, model, Player version or tag as one notice with one recovery (NotificationDeliveryGroup); the other screens' notices are skipped as grouped.

    A webhook still sends one notice per screen. event_types are POSTed as the same JSON object GET /api/events returns.

    Every POST carries ScreenRig-Webhook-Id (the notification id), ScreenRig-Event-Id (the delivery id for a notice, the event cursor for an event; stable across retries, deduplicate on it), User-Agent, and ScreenRig-Signature t=<unix seconds>,v1=<hex HMAC-SHA256 over "<t>.<raw body>" keyed with the secret string>.

    A 2xx answer within 10 seconds succeeds; anything else is retried with exponential backoff (30 seconds doubling to one hour, jittered) for 24 hours and then failed; email failures retry the same way.

    Screen notices and screen.* events are free; other events are metered like a listen-stream event. status is failing while nothing has succeeded since failing_since; after 72 hours of continuous failure the notification is disabled (disabled_reason delivery_failures) and notification.disabled is appended.

  • NotificationActiveHours — required: timezone, windows

    When opened notices go out: the windows (screenrig.schedule/v1), read in timezone. A notice that falls due while they are closed waits for the next opening (outside hold, the default) and goes out then if its condition still holds, so a condition that clears first sends nothing, or is skipped (outside drop; last_error outside_hours).

    A resolved notice for an opened notice that was sent always goes out, inside the hours or not, and a test ignores them. crashing is held or dropped like any other condition. The hours judge a notice when it first goes out; a failed one is retried on the usual schedule whatever the hours.

    Adding, changing or removing the hours judges the notices held for the old ones again at once.

  • NotificationCondition — required: none

    An important screen state change. screen_offline: the Player lost its connection (screen.offline, written 60 seconds after its presence lapses); clears on screen.online. display_disconnected: the Player reports its display disconnected (screen.health_changed change display_disconnected); clears on display_reconnected. running_hot: the device reports a temperature at or above the hot threshold (temperature_high); clears on temperature_normal. on_battery: the device has a battery and its latest health report names a battery source of none, which is unplugged (screen.health_changed change on_battery); clears when a report names any other source (plugged_in).

    The notice says the screen runs on its battery and names no cause. storage_full: the Player's storage cannot hold its content (screen.storage_shortfall); clears on screen.storage_shortfall_cleared. content_stuck: the screen's content update is retrying, failed, blocked or partial (screen.manifest_upgrade); clears when a later state is none of those. not_playing: the Player shows an error-level status instead of its content (screen.status_changed with level error, other than storage_full); clears when its status is no longer an error. loop_stalled: the Player reports nothing wrong and its content is current, yet no media start has reached the backend for longer than the screen's loop allows (screen.glass_changed with the playback verdict stalled; Screen.glass says when it judges and what it leaves alone); clears when a media start arrives or the screen stops being judged, for instance when it goes offline. glass_blank and glass_frozen: the backend read the screen's screenshots over a run that covers its loop and every one was a flat tone (glass_blank) or the same picture (glass_frozen) (screen.glass_changed with the picture verdict blank or frozen; Screen.glass says when it judges and what it leaves alone); clears when two screenshots in a row show a moving picture or the screen stops being judged.

    A screen that stops being judged closes the alert, but email and chat notifications send no recovery notice for it, since nothing was seen to recover (the resolved row is skipped as no_longer_judged); a media start or two good screenshots do send one. crashing: the Player crashed or restarted its renderer repeatedly (screen.health_changed change crash_spike or renderer_restart_spike); sent at once, never held or resolved. source_failed and source_stale are about a data source, not a screen: the notice's screen member carries the source's id and name, the link is the source's page, and screen_tags never matches a source, so a notification scoped to tags does not watch them. source_failed: a refresh of the source failed (source.status_changed with state error); clears on the next refresh that works (state ok). source_stale: the source's last good refresh is older than its stale_after_seconds, the point its card data expires and pages that depend on it fall back (source.stale); clears on the next refresh that works.

    Neither is a screen alert. reach_dropped and group_empty are about a campaign (a shared level of the schedule stack), not a screen: the notice's screen member carries the campaign's id and name, the link is the campaign's calendar in the dashboard, and a campaign is the project's, so screen_tags and audience never limit them. reach_dropped: a recount found the campaign reaching fewer screens than when it was last published, because screens left one of its tags or folders, were archived or deleted (campaign.reach_changed with current below published); reach_drop sets how large a drop is notified; clears when it reaches as many screens again.

    A publish that sets a new baseline, or deleting the campaign, also clears it, which closes a pager incident and a webhook's alert but sends no recovery mail or chat notice (no_longer_judged). group_empty: a tag or folder of the campaign's audience matches no screen (campaign.group_changed with matched 0); one notice per tag or folder (audience_group); clears when it matches a screen again, or when a publish removes it from the audience (removed true), which closes a pager incident and a webhook's alert but sends no recovery mail or chat notice (no_longer_judged).

    A screen's own schedule entries target playlists, not screens, so only campaigns have a reach.

    Neither is a screen alert. card_data_stale is about a card, not a screen: the notice's screen member carries the card's id and its name (the card's type, as in "weather card"), the link is the dashboard's page editor on a page that places the card (the notification's own page when none does), and since is when its data expired.

    It opens when a card's data document that an agent, a job or a person wrote with an expiry (ttl_seconds or expires_at, as in card data put --ttl) reaches that expiry without another write to renew it, while a screen shows the card (card.data_expired), so the card is blank on that screen; it clears when a write to the card's data lands (card.data_renewed).

    A data source's documents are not announced: they expire by the source's stale period and source_stale covers them. A card no screen shows sends nothing, and neither does one that was renewed, deleted or taken off every screen before the notice is due.

    Deleting a card's data ends the notice without a recovery notice, as a publish ends a drop (no_longer_judged). Size ttl_seconds to the writer's schedule, so a job that stopped is noticed. Like a data source, a card has no screen tags: a notification scoped to screen_tags does not watch cards, and it is not a screen alert.

    Readers treat an unknown value as absent.

  • NotificationConditions — required: none
  • NotificationDelivery — required: id, notification_id, event_id, event_type, state, attempts, created_at
  • NotificationDeliveryAttempt — required: attempt, at, status, error, duration_ms
  • NotificationDeliveryAttemptList — required: items
  • NotificationDeliveryGroup — required: id, attribute, value, count

    A group of screens one notice stands for. When at least three screens of a project fall into the same condition within five minutes of one another and share a value, an email, Slack, Teams, PagerDuty or Telegram notification sends one notice for them instead of one per screen.

    A screen that falls into the condition later with a value the open group is made of joins it without a new notice, and one notice says the group when its last screen recovers. A webhook notification still sends one notice per screen.

  • NotificationDeliveryList — required: items, next_cursor
  • NotificationDestination — required: none

    Slack, Teams, PagerDuty and Telegram only; required for them. The credential in the shape the service issues it: slack, the incoming webhook URL (hooks.slack.com); teams, the Workflows webhook URL (logic.azure.com or powerplatform.com; Office 365 connector URLs are retired); pagerduty, the 32-character Events API v2 routing key; telegram, the bot token.

    Another shape is notification_destination_rejected. It is sealed, never returned, and appears on reads only as destination_hint.

  • NotificationEventTypes — required: none

    Webhook only. Project events also POSTed as they happen, exactly as a webhook sends them: exact types such as screen.online, or prefixes ending in .* such as screen.*. notification.test is never fanned out.

  • NotificationList — required: items
  • NotificationPatch — required: none
  • NotificationProjectIDs — required: none

    Live projects of the organization, each named once. An empty list covers none.

  • NotificationReachDrop — required: none

    The smallest drop in a campaign's reach a reach_dropped notice is sent for: screens is the fewest screens lost (default 1) and percent, when set, the smallest share of the screens the campaign reached when it was published; a drop must meet both.

    A smaller drop queues no notice, and a queued notice whose drop shrank below it by the time it is due is skipped (condition_cleared). Only with the reach_dropped condition; on a notification without it, invalid_request.

  • NotificationRecipients — required: none

    Email only. owner (whoever owns the project when a notice sends) or the user_id of a person who is a member of the project; a user_id that is not a member is invalid_request. Each is emailed at their verified address. One who has since left the project or has no verified address is skipped.

  • NotificationSeverity — required: none

    The severity of a notice, least severe first. An opened notice has its condition's severity: error for screen_offline and warning for every other condition, unless the notification's severity says otherwise. A resolved notice and a test are info.

  • NotificationSeverityOverrides — required: none

    Condition to severity for this notification, such as {"not_playing": "error"}. It counts for min_severity and is the severity Teams and PagerDuty show for the condition. A condition not listed keeps its default. On a patch an empty object, like null, clears every override.

  • NotificationTelegramChat — required: none

    Telegram only; required for it. The chat to post to: its numeric id (negative for a group or channel) or @channelname. Not a credential.

  • NotificationUnsubscription — required: user_id, at
  • NotificationWrite — required: channel

    email sends to recipients, webhook POSTs signed to url, and slack, teams, pagerduty and telegram post one message per outage and screen to a chat or pager with the write-only destination (telegram also needs telegram_chat_id), then a recovery after it; PagerDuty opens an incident and resolves it. They need at least one condition and take no event_types.

  • OAuthAuthorization — required: id, client_name, client_registered, redirect_host, access, capabilities, created_at, expires_at
  • OAuthAuthorizationRedirect — required: redirect_uri
  • OAuthError — required: error
  • OAuthTokenResponse — required: access_token, token_type, expires_in
  • OnboardingSiteCTA — required: label, path, href, at

    The sign-up or sign-in link the person clicked on the website.

  • OnboardingSiteVisit — required: path, at
  • OnboardingStepName — required: none

    A step of the entry flows, in display order. email_verified, email_gate_reached and the account milestones (agent_connected, screen_paired, playlist_with_content, activated) are written or joined by the server and are not names a client sends.

  • OnboardingStepRequest — required: journey_id, step
  • OnboardingValue — required: none

    What the person entered at a step: the address typed (email_submitted, reset_requested), the name (signup_name_entered), yes or no (signup_marketing_choice), the options chosen or the follow-up text (question_answered, question_follow_up), an address or name entered on an invitation. Never a password, code or token. Empty is absent.

  • Operation — required: id, kind, state, created_at, updated_at
  • OperationAccepted — required: id, release_id, operation_id
  • OrganizationAdminInvitation — required: id, kind, delivery, status, recipient_email, organization_id, created_at, expires_at
  • OrganizationAdminInvitationCreate — required: emails
  • OrganizationAdminInvitationCreated — required: invitations
  • OrganizationAdminInvitationList — required: items, next_cursor
  • OrganizationAdmins — required: admins, candidates, revision
  • OrganizationAdminsUpdate — required: admin_user_ids
  • OrganizationBillingUsage — required: org_id, period, pool, allowance, stored_bytes, screens, projects, next_cursor
  • OrganizationDomainChallenge — required: organization_id, challenge_id, domain, name, value, expires_at
  • OrganizationDomainInput — required: domain
  • OrganizationDomainProof — required: challenge_id
  • OrganizationDomainRemoved — required: status
  • OrganizationGuestPolicy — required: mode, domains

    The organization's guest policy in force. Guests are people whose home organization is another one, or who have none; a policy never removes anyone who is already a member.

  • OrganizationGuestPolicyDomain — required: none

    A lowercase DNS name with at least two labels, as it appears after the @ of a verified email address (internationalized names in their xn-- form).

  • OrganizationGuestPolicyMode — required: none

    allow admits every guest. domains admits a guest whose verified email address is at one of the listed domains (exact match). none admits no guest. Home members are never guests.

  • OrganizationGuestPolicyResult — required: mode, domains, outside_policy

    The guest policy now in force, with how many people it leaves outside.

  • OrganizationGuestPolicyUpdate — required: mode
  • OrganizationLibraryUpdate — required: project_id
  • OrganizationList — required: organizations, new_organization_allowed
  • OrganizationMemberInvitation — required: id, kind, delivery, status, recipient_email, organization_id, created_at, expires_at
  • OrganizationMemberInvitationCreate — required: emails
  • OrganizationMemberInvitationCreated — required: invitations
  • OrganizationMemberInvitationList — required: items, next_cursor
  • OrganizationNotificationList — required: items
  • OrganizationNotificationPatch — required: none

    A NotificationPatch and project_ids.

  • OrganizationNotificationWrite — required: channel

    A NotificationWrite and the projects the notification covers. Absent or null project_ids covers every project of the organization, including projects added later; a list covers exactly those projects, each a live project of the organization.

  • OrganizationPayments — required: organization_id, available, local_simulation, purchases
  • OrganizationPeople — required: projects, people, truncated
  • OrganizationPeopleMembership — required: project_id, role, can_approve
  • OrganizationPeoplePerson — required: user_id, display_name, email, admin, member, managed, outside_guest_policy, projects
  • OrganizationPeopleProject — required: project_id, name
  • OrganizationPerson — required: user_id, display_name, email
  • OrganizationPersonal — required: none

    The organization is only its one project's wrapper: exactly one live project, no verified domain, no organization plan now or scheduled, and no admin other than that project's owner. The dashboard hides the organization level for it.

  • OrganizationProject — required: id, name, organization_id, status, screen_count
  • OrganizationProjectAccess — required: project_id, joined
  • OrganizationProjectAccessChange — required: project_id, user_id, access
  • OrganizationProjectAccessRequest — required: changes
  • OrganizationProjectAccessResult — required: changes
  • OrganizationProjectOwner — required: project_id, owner_user_id
  • OrganizationProjectOwnerUpdate — required: user_id
  • OrganizationProjectPage — required: projects, next_cursor
  • OrganizationRename — required: name
  • OrganizationSummary — required: id, name, personal
  • OrganizationView — required: id, name, personal, revision, admin, home, project_count, plan_id, free, plan_required, education_eligible, education_eligibility_source
  • PageDataCondition — required: key

    A card-data predicate, evaluated before civil time. Missing or expired data never matches. The page also respects its ordinary time bounds. Requires host capability page.conditions; older hosts receive the page disabled.

  • PageFailure — required: page_id, code, at

    Latest accepted playback.page_failed report for this screen. Absent until a player reports one. Read-only project health metadata; it does not change screen revision or manifest authority.

  • PageVisibility — required: enabled

    Optional page visibility schedule. It is a sibling of advance and is never part of screenrig.canvas/v1; it describes playback orchestration, not geometry. The server validates and carries these rules as data. The player evaluates them against the screen timezone published at the manifest root.

    A page is eligible when enabled is true, now is inside [from, until), and either windows is absent or at least one window matches. Every playlist must keep at least one page with no visibility field at all, so eligible content always exists. Conformance vectors for the evaluation rules are the screenrig.schedule/v1 family in packages/schedule-contract.

  • PageVisibilityWindow — required: days

    One recurring civil window. Omitting start and end selects the whole day. When end is less than or equal to start the window crosses midnight and the start day owns it, so fri 22:00 to 02:00 runs into Saturday morning.

  • PairScreen — required: code
  • PairingClaim — required: screen, public_url
  • PairingClaimedEvent — required: type, completion_nonce
  • PairingComplete — required: completion_nonce
  • PairingCompletion — required: screen, public_url
  • PairingSession — required: code, expires_at
  • PasskeyAdditionProof — required: authorization_ceremony_id, authorization_credential
  • PlaybackAggregate — required: screen_id, media_id, filename, day, play_count, last_page_id, last_manifest_revision, first_started_at, last_started_at
  • PlaybackAggregateCsv — required: none

    RFC 4180 CSV, CRLF records, UTF-8, with the header row screen_id,media_id,filename,primitive,day,play_count,last_page_id,last_manifest_revision,first_started_at,last_started_at. Times are RFC 3339 UTC. A cell beginning with =, +, -, @, tab, or carriage return is prefixed with a single quote so spreadsheets do not evaluate it.

    Content-Disposition names playback-aggregates.csv. A stream that fails after the header is aborted at the connection.

  • PlaybackAggregateList — required: items
  • PlaybackApplicationStartedContext — required: manifest_revision, page_id, primitive_id, release_id
  • PlaybackApplicationStartedReport — required: severity, code, context

    One visible start of an application primitive on a page: the application became visible on glass, reported once per page appearance by the Player controller — the application content never reports its own visibility, and a package download is never a start.

    The sending screen is authenticated; page, primitive, release and manifest identities are reported observations without content or grant membership checks. Stores one durable per-play record (GET /api/playback/plays). Project-owned release/application housekeeping timestamps follow through a recoverable batch projection.

    Ordinary playback acknowledgments omit optional credit balance headers. There is no daily aggregate row for application starts; the play records are the evidence.

  • PlaybackCompleteness — required: day_from, day_to, measured_plays, missing_plays, completeness, days, gaps, truncated

    How many of the plays the screens made reached the backend, over the inclusive UTC days day_from to day_to. measured_plays and missing_plays are the sums of days, and completeness is measured_plays over their sum, null when both are 0. days lists, oldest first, only the days with a measured or a missing play. gaps lists the holes in the play numbering, newest first.

    Plays without a number (older Players, starts stored before play numbers) are in none of these figures.

  • PlaybackCompletenessDay — required: day, measured_plays, missing_plays, completeness

    The play numbering of one UTC receipt day.

  • PlaybackCompletenessShare — required: none

    Plays that arrived over plays that arrived plus plays that went missing, from 0 to 1. null when there are neither, as for older Players that number no plays.

  • PlaybackGap — required: screen_id, day, from, to, missing_plays

    One run of play numbers a Player skipped, so that many plays were made and never arrived.

  • PlaybackGrant — required: none

    The playback handshake the backend granted: the intersection of the mint's PlaybackHandshake and what this backend supports, signed into the session. Omitted from the session when nothing intersects, so a session minted without a handshake is unchanged. A Player uses /screen/manifest only when manifest_versions contains 3.

  • PlaybackHandshake — required: none

    Optional playback handshake a Player declares at mint. It is a hint that selects behavior, never authorization: unknown members and entries of the wrong type are ignored, and a value that is not an object negotiates nothing. The mint response echoes the supported intersection as PlaybackGrant. adslot-v1 is granted only to paired sessions.

  • PlaybackMediaStartedContext — required: media_id, manifest_revision, page_id, primitive
  • PlaybackMediaStartedReport — required: severity, code, context

    One visible start of an image or video primitive on a page. Players send this once per page appearance of the media, for images exactly as for videos; loops inside one appearance are not restarts. The sending screen is authenticated; media, page, primitive and manifest identities are observations without content or grant membership checks.

    Success acknowledges durable raw insertion; daily counts follow through a recoverable batched projection. Ordinary playback acknowledgments omit optional credit balance headers.

  • PlaybackPageFailedContext — required: page_id, code
  • PlaybackPageFailedReport — required: severity, code, context

    Reports that one page could not become ready. On acceptance the server replaces Screen.last_page_failure and appends a durable project-only playback.page_failed event in the same transaction. It does not change screen revision or manifest authority.

  • PlaybackPlay — required: screen_id, page_id, media_id, primitive, received_at

    One durable Player-reported start of an image, video, or application.

    The session authenticates screen and project; item, page, manifest, primitive and release identities are reported observations and do not authorize content access. playlist_id and playlist_revision are optional metadata enriched asynchronously from a matching screen manifest; missing metadata stays absent.

    Application starts carry release_id with empty media_id and primitive. primitive_id and started_at are present only when the Player reports them; started_at is clamped to [received_at - 24h, received_at + 5m].

    A JSON page also names its screen, media, playlist and application as display text read when it is served; the CSV export and the xlsx and pdf reports omit those names.

  • PlaybackPlayCsv — required: none

    RFC 4180 CSV, CRLF records, UTF-8, with the header row screen_id,playlist_id,page_id,primitive_id,media_id,primitive,started_at,received_at,manifest_revision,playlist_revision in that fixed order; an absent value is an empty cell. Times are RFC 3339 UTC. A cell beginning with =, +, -, @, tab, or carriage return is prefixed with a single quote.

    Content-Disposition names playback-plays.csv. A complete export ends after its last CRLF record with no trailer; a stream that fails after the header is aborted at the connection (the client sees a transport error, never a clean end), so retry from the last received_at.

  • PlaybackPlayList — required: items, next_cursor
  • PlaybackTotals — required: by, day_from, day_to, truncated

    Play totals over the inclusive UTC days day_from to day_to. Exactly one of days (by=day), screens (by=screen), media (by=media) or screen_days (by=screen_day, grouped by screen in rank order, days ascending) is present, the one the request named. truncated is true when a ranking may leave out keys that ranked below the best of a slice or a store.

  • PlaybackTotalsDay — required: day, play_count, first_started_at, last_started_at
  • PlaybackTotalsMedia — required: media_id, play_count, first_started_at, last_started_at
  • PlaybackTotalsScreen — required: screen_id, play_count, first_started_at, last_started_at
  • PlaybackTotalsScreenDay — required: screen_id, day, play_count
  • PlaybackVideoStartedContext — required: media_id, manifest_revision, page_id
  • PlaybackVideoStartedReport — required: severity, code, context

    Report one visible video start. This uses the same daily aggregation as playback.media_started with primitive video. Send one report per start; sending both event types counts the start twice. Use playback.media_started when reporting both images and videos.

  • PlayerBrowserIdentity — required: kind, version, pwa

    Browser engine and installation mode for browser Players, including native shells. A malformed optional browser hint is dropped without rejecting the mint.

  • PlayerCardsIdentity — required: none

    The built-in cards library the Player carries (docs/player-compatibility.md §3.1): the library CalVer and each card's semver, whose major says which card placements the screen renders. Stored on the screen with the rest of player. Malformed entries are dropped one by one; it is never a 400.

  • PlayerIdentity — required: kind

    Player self-identification, sent only on the three mint routes (docs/player-compatibility.md §3.1). It is a hint and never authorization, and it is not covered by the native proof. It is read tolerantly: unknown members are ignored, an invalid optional member is dropped on its own, and a player that is not an object or has no valid kind declares nothing.

    It is never a 400. A paired mint stores it on the screen for the operator fleet histogram.

  • PlayerPublicKey — required: kty, crv, x
  • PlayerShellIdentity — required: kind

    The shell a web Player runs under. Its compat tokens are recorded, never granted. An invalid kind drops the shell.

  • Playlist — required: id, name, revision, pages
  • PlaylistAdvance — required: none
  • PlaylistAdvanceWrite — required: none
  • PlaylistApplicationAdvance — required: mode, max_ms
  • PlaylistApplicationPrimitive — required: id, primitive, release_id, rect, layer, content_fit
  • PlaylistApplicationPrimitiveWrite — required: id, primitive, release_id, layer, content_fit
  • PlaylistApproval — required: state, review_id

    Present while a review of this playlist is pending. The playlist itself is the live (approved) version.

  • PlaylistAudio — required: tracks, loop, volume

    Stored playlist soundtrack with defaults filled in.

  • PlaylistAudioCue — required: track

    Optional soundtrack hint on an ordinary page. When the page becomes current, the Player switches to the named track from its start unless it is already playing; restart true restarts it even then. The sequence continues from that track.

    Players may ignore a hint. track must name a track id in the playlist audio; a cue without a playlist audio is invalid_request. Not allowed on adslot pages. A page with advance mode audio_end ends when the cued track ends; it requires this cue.

  • PlaylistAudioEndAdvance — required: mode, max_ms
  • PlaylistAudioEndAdvanceWrite — required: mode

    The page ends when the soundtrack track its audio_cue names ends. The page must carry an audio_cue and the playlist an audio soundtrack (docs/playlist-audio.md).

  • PlaylistAudioTrack — required: id, media_id
  • PlaylistAudioWrite — required: tracks

    Optional playlist soundtrack: ordered ready audio (MP3) media that plays continuously while pages change (docs/playlist-audio.md). Page changes never stop or restart it. PUT replaces the whole playlist, so omitting audio removes the soundtrack.

  • PlaylistCanvas — required: width, height, background
  • PlaylistCardPrimitive — required: id, primitive, card, major, params, rect, layer, content_fit, controller
  • PlaylistCardPrimitiveWrite — required: id, primitive, card, layout, content_fit

    A built-in card the Player draws natively (clock, weather, menu board, ticker, KPI tiles and the rest of the vendored cards catalog, screenrig.cards.contract/v1). layout places it: full (the whole canvas), free (your own rect and layer), center (900 x 420), wide (the canvas inset 30 from the left and right and 80 from the top and bottom), header (the whole top edge, 80 high), footer (the whole bottom edge, 80 high), corner (270 square), chip (240 x 70) or strip (the whole edge, 120 high), in 1080p design units scaled by min(canvas width, canvas height) / 1080. corner and chip take an anchor corner (top-left, top-right, bottom-left, bottom-right) and strip an anchor edge (top, bottom, left, right); the other layouts take none.

    Except for free, the server derives rect and layer from the canvas, or from the frame displays cover: omit them, or send exactly what it derives.

    A page holds at most one full, center or wide card, one corner or chip card per corner, and one strip per edge (a card with presence may share an edge with a normal strip); a header takes the top edge's normal strip slot and a footer the bottom edge's, so a page holds at most one of each, no normal strip on that edge, and a card with presence may still share it.

    A corner or chip on an edge that holds a strip moves in past it by 120, and past a header or footer by 80.

    On a playlist with a format, displays is the frame the layout derives in (full is the frame, corner the frame's corner; free refuses displays), the card scale is the tile's min(width, height) / 1080 = 1 rather than derived from the frame, and two cards compete for a slot, or move in past each other's strips, only when their frames share a display (no displays is every display).

    A card's tier decides its layouts (GET /api/card-types): core takes all nine, fullscreen takes full. params holds the placement's static properties (theme, location, titles, column definitions) and changes only with a republish.

    A string in params may carry {screen.name}, {screen.timezone} and {screen.field.NAME}, and a location param may be the string {screen.location}; the backend expands them for each screen, so one playlist shows every screen its own values. data names a card data document (GET/PUT /api/card-data/{key}) that holds the card's dynamic properties (menu sections, ticker items, KPI tiles); agents change it without a republish. {screen.field.NAME} in a data key reads a per-screen document, for example menu-{screen.field.store_number}.

    With data, params may not carry dynamic properties; without it, params carry the whole configuration. Every string in params that begins with media: is a media reference, media:<id>, naming a ready image in this project that the card draws (spotlight people[].photo, product-grid products[].photo); a card never takes an image URL.

    Publish refuses an unknown card or major and invalid params (card_invalid), a layout, anchor, rect or layer the card may not carry (card_layout_invalid), cards that claim one place on the page (card_layout_conflict), a media reference that names no ready image of the project (card_media_invalid), and a bound key whose stored document the card rejects (card_data_invalid).

    The screens showing the placement are granted its media, and a live write approves pending media it names, as with a by:id selector. A card with a third-party feed (weather) reads it from the key the server derives from its static params.

  • PlaylistCreateRequest — required: none

    A playlist's pages, or a template to make it from, or the built-in starter.

  • PlaylistDisplays — required: none

    Playlists with a format only. The displays a primitive covers: ascending unique 1-based display numbers within 1..format.displays that fill a rectangle of the wall's tiles, such as [2], [1, 2] or, on a grid of 4 columns, [2, 3, 6, 7]. In a row or a column they are contiguous.

    The server derives rect as the bounding box of those tiles; rect is omitted or exactly the derived value. Stored and echoed on read.

  • PlaylistDurationAdvance — required: mode, after_ms
  • PlaylistExpandRequest — required: none
  • PlaylistExpanded — required: pages
  • PlaylistFormat — required: none

    What a playlist is authored for: a video wall (PlaylistWallFormat) or a region (PlaylistRegionFormat), never both. A playlist without a format is an ordinary playlist that binds to any screen as the page.

  • PlaylistFromTemplate — required: playlist_id

    Creates a playlist from a template: its current pages with the values filled in, validated by every playlist rule. A media value must be a ready media item of the right kind, a url value an http or https address.

  • PlaylistFromTemplateWrite — required: name, from_template

    Creates a playlist from a template. Send only name and from_template.

  • PlaylistIframePrimitive — required: id, primitive, src, title, rect, layer, content_fit, controller
  • PlaylistIframePrimitiveWrite — required: id, primitive, src, title, layer, content_fit
  • PlaylistImagePrimitive — required: id, primitive, selector, resolved_media, rect, layer, content_fit, controller
  • PlaylistImagePrimitiveWrite — required: id, primitive, selector, layer, content_fit
  • PlaylistInstance — required: id, name, revision, template_revision, outdated
  • PlaylistInstanceList — required: items
  • PlaylistIntrinsicSize — required: width, height
  • PlaylistList — required: items
  • PlaylistMediaEndAdvance — required: mode, max_ms
  • PlaylistMediaEndAdvanceWrite — required: mode
  • PlaylistMediaSelector — required: none
  • PlaylistMediaSelectorByAll — required: by
  • PlaylistMediaSelectorByFolder — required: by, folder_id

    The ready files of the primitive directly inside one media folder (GET /api/media-folders), not those of its subfolders, ordered and paced like by:all. Like a tag, the folder is read again at every selector resolve, so moving files in or out changes what playing screens show from their next loop.

    Writing a playlist requires the folder to exist in the project; it may be empty. A folder that holds no ready file of the primitive, or is deleted later, matches nothing. Players receive it as by:all; the server resolves the folder.

  • PlaylistMediaSelectorByID — required: by, media_id
  • PlaylistMediaSelectorByIDs — required: by, media_ids
  • PlaylistMediaSelectorByTag — required: by
  • PlaylistPage — required: id, canvas, transition, advance, primitives
  • PlaylistPageAdd — required: page
  • PlaylistPageStructure — required: id

    One page that stays, and the two page settings a person changes. advance replaces the page's advance when present and keeps it when omitted; an ad slot page has none. visibility replaces the page's visibility when an object, removes it when null and keeps it when omitted.

    A visibility object that only sets enabled true is a no-op and is rejected: send null to remove the rules.

  • PlaylistPageV2 — required: none
  • PlaylistPageWrite — required: id, canvas, transition, advance, primitives
  • PlaylistPageWriteV2 — required: none
  • PlaylistPatch — required: none

    Omitted fields are preserved. Supplied name, pages, audio and format replace those top-level values; audio or format null removes it. Supplied pages are checked against the stored format when format is omitted, and a supplied format against the stored pages when pages is omitted. Identity, revision, comments and timestamps cannot be set here.

    Comments have their own endpoints.

  • PlaylistPrimitive — required: none
  • PlaylistPrimitiveLocked — required: none

    A locked primitive is fixed brand content of a template (logo, background, layout, theme): only the project owner or a member who can approve adds, removes, moves or edits it, or clears its lock, and a playlist made from the template keeps it locked. Omitted means unlocked. A locked primitive cannot read a field.

    A write by anyone else is primitive_locked (403), or a review under Propose.

  • PlaylistPrimitiveWrite — required: none
  • PlaylistRect — required: x, y, width, height
  • PlaylistRegionFormat — required: region, orientation

    A strip drawn over the page along one edge of a display: a header at the top, a footer at the bottom, a side at the right edge at full height. orientation is the orientation of the display it is made for, as the viewer sees it after rotation.

    Every page has the same canvas (width and height); a header or footer is wider than tall and a side taller than wide, with the long side at least twice the short side, else 400 invalid_request at pages[i].canvas.

    The playlist holds image and card primitives only (a video, stream, iframe, application or ad slot page is refused) and has no soundtrack (audio is refused); a primitive names no displays.

    A region playlist is never a screen default, a folder default or a takeover: it plays as a schedule entry or a campaign with covers set to its region (covers main and the full page refuse it), and covers header, footer or side needs a region playlist of that region.

    The entry or campaign is refused with 409 playlist_format_mismatch when the strip is laid out on none of the displays it targets: a strip is laid out on a display of its orientation, judged on the surface the Player reports after rotation (the screen's wall rotation when it has not reported one), and only while it would cover no more than half of the display (its height for a header or footer, its width for a side).

    A campaign is refused only when it is laid out on none of the screens of its audience; on a screen of a mixed audience where it is not, the campaign leaves that screen's stack and its explanation says region_not_laid_out.

    A format change that moves a playlist into or out of a region, or to another region, is refused with 409 resource_conflict while a screen schedule, takeover or default, a folder default or a campaign uses it.

  • PlaylistResolvedMedia — required: media_id, intrinsic_size
  • PlaylistRevision — required: revision, created_at, change, name, page_count, current

    One stored revision of a playlist. change says what made it: created (the first revision), edited (a replace, patch, structure change or applied review), promoted (a copy of an earlier revision, named by restored_from), or baseline (the revision the playlist held when its history began, before any write recorded one).

    A value this reader does not know reads as edited.

  • PlaylistRevisionAuthor — required: type, name

    Who made the revision, as the project's event log names them; absent when the write named no one (a baseline, or system work).

  • PlaylistRevisionDetail — required: revision, playlist
  • PlaylistRevisionList — required: items
  • PlaylistStarterWrite — required: starter

    Adds the built-in Urgent notice template (a headline and a message). Send only starter, and optionally name.

  • PlaylistStinger — required: none

    A transition-only stinger card (major 1). All members are optional; defaults stay in the synthetic runtime placement. hang_ms defaults to 1000 and is at most 60% of the transition duration_ms (checked by the server). logo names a ready image in this project, using the card media grant path.

  • PlaylistStreamPrimitive — required: id, primitive, sources, fallback_media_id, rect, layer, content_fit, muted, controller, resolved_media
  • PlaylistStreamPrimitiveWrite — required: id, primitive, sources, fallback_media_id, layer, content_fit
  • PlaylistStructurePatch — required: none

    A playlist's structure and nothing a page shows (patchPlaylistStructure). Omitted members are kept. A supplied name replaces the name. A supplied pages is the complete new order of the pages the playlist holds: a stored page it omits is removed.

    Page content (canvas, transition, audio_cue, primitives, comments) and the soundtrack cannot be sent and are always the stored ones.

  • PlaylistTemplateField — required: name, label, type

    One value a template takes. Pages read it as {field.NAME}: in a card's params (text and url fields), as an image or video selector media_id (media field) or as the whole src of an iframe (url field).

  • PlaylistTemplateFields — required: none

    Declaring fields makes the playlist a template. Every token a page reads must name a declared field of the right type and every field must be read; a playlist without fields reads no tokens. A template is never shown on a screen (playlist_is_template). PUT without fields keeps them; null or an empty array removes them.

  • PlaylistTransition — required: type, duration_ms

    Page transition. type and duration_ms are both required; OpenAPI does not default them. Swipe authoring examples use duration_ms 600; that value is not a schema default.

  • PlaylistV2 — required: id, name, revision, pages
  • PlaylistV2List — required: items
  • PlaylistValuesChange — required: values
  • PlaylistVideoPrimitive — required: id, primitive, selector, resolved_media, muted, loop, rect, layer, content_fit, controller
  • PlaylistVideoPrimitiveWrite — required: id, primitive, selector, layer, content_fit
  • PlaylistWallFormat — required: displays, arrangement, orientation

    The video wall a playlist is authored for: 2 to 12 displays, tiles of 1920 x 1080 (landscape) or 1080 x 1920 (portrait), laid out in a row, a column or a grid. A row has the displays as columns and one row, a column one column and the displays as rows, a grid columns and displays / columns rows.

    Display n sits at column (n - 1) mod columns and row floor((n - 1) / columns): left to right, then top to bottom.

    The canvas of c columns and r rows of tiles of width w and height h is (c * w, r * h), for example 5760 x 1080 for 3 landscape displays in a row, 1080 x 3840 for 2 portrait displays in a column and 7680 x 3240 for 12 landscape displays in a grid of 4 columns.

    Every ordinary page's canvas width and height must equal it exactly, else 400 invalid_request at pages[i].canvas. Card scale on such a playlist is the tile's min(width, height) / 1080 = 1.

    A playlist with a format may be bound only to a screen whose wall has the same shape (displays = number of outputs, arrangement, columns, portrait if and only if rotation is 90 or 270), else 409 playlist_format_mismatch: assignment, fleet assignment, schedule entries and takeover. A playlist without a format binds to any screen.

  • PlaylistWarning — required: code, message, page_id, primitive_id

    Something the author of a successful write should act on. The write stored what it carried; a warning never fails it. A playlist write answers with warnings on the playlist; a screen write (updateScreen, the dashboard's fields, location and playlist routes) on the screen; a fleet assign on the result page.

    Two codes. iframe_framing_refused: a public https page named by an iframe primitive (its src or its fallback_src) sends X-Frame-Options (DENY, SAMEORIGIN or the obsolete ALLOW-FROM) or a Content-Security-Policy frame-ancestors list that does not admit the Player web app's origin.

    The Player web app and the macOS, Samsung Tizen, LG webOS and BrightSign Players frame the page, so they cannot show it; Android, Linux and Windows Players open an iframe page as a whole page and are not affected.

    The backend reads the page's response headers once the write commits, for at most 8 distinct pages per write; a page it cannot reach in time, or that answers an error, is not reported. Each distinct page appears once, naming the first primitive that uses it, and appends one playlist.iframe_framing_refused event (warning) to the project's event log.

    A src with screen tokens is not one page and is not read. screen_fact_missing: a screen the write reaches lacks a value that an iframe's src or an application's params read through a screen token ({screen.field.NAME}, {screen.location.…}, {screen.timezone}), or the values it has fill into one the manifest refuses (an address over 2048 characters, a path segment of . or .., launch params over 4096 characters in the launch URL), so the primitive is left out of that screen's manifest (manifest diagnostic screen_fact_missing or screen_fact_invalid) until the screen has the value.

    One warning per write names the first such primitive, the tokens no listed screen could fill (at most 64), the first 20 affected screens and how many there are.

    A playlist write (a replace, patch, structure change, promote or applied review) reaches the screens that show the playlist; a screen write reaches that screen, for the playlist it shows and the one it was just assigned; a fleet assign reaches the screens of its page; approving a screen change reaches the screens it names.

  • PlaylistWrite — required: name, pages
  • PlaylistWriteV2 — required: name, pages
  • PrimitiveEnter — required: type

    Optional object enter. Playlist write and the runtime manifest use this object as-is; there is no snake_case rename inside it. Absent means paint at rest, full opacity. Optional integer stagger 0 through 8 delays start by stagger*120 ms after the shared 500 ms delay. Absent or 0 is today's start. Duration is a named constant in screenrig.canvas/v1.

  • PrimitiveMotion — required: none

    Optional persistent object motion. Playlist write and the runtime manifest use this object as-is; there is no snake_case rename inside it. Absent means the primitive stays at rest after enter.

    Copied through uninterpolated. spin and drift apply to image and video only; application and iframe with spin or drift are rejected by the server (motion_not_allowed_for_primitive). path applies to image, video, application, and iframe. This restriction is not encoded as OpenAPI if/then.

  • PrimitiveMotionDrift — required: type, zoom, direction, speed

    Continuous slow scale about the clipRect centre combined with a slow translate. Image and video only; the server rejects drift on application and iframe. Ping-pongs; never jumps.

  • PrimitiveMotionPath — required: type, points, rate

    Translation along a polyline of canvas-unit waypoints after the authored rect. loop defaults to loop when omitted. Valid on image, video, application, and iframe.

  • PrimitiveMotionPoint — required: x, y
  • PrimitiveMotionSpin — required: type, direction, speed

    Continuous rotation about the clipRect centre. Image and video only; the server rejects spin on application and iframe.

  • Problem — required: errors, instance, request_id

    The problem document every route answers except the Player-facing runtime, content, and probe routes (RuntimeProblem). The error itself is errors[0]: its status, code, type, title, detail, and hint. Only document members stay at the top level. Branch on errors[0].code, never on detail or hint, which are prose.

    A blamed request field adds errors[0].field; each further blamed field is its own entry with that field's detail.

  • ProblemError — required: status, code, type, title, detail, hint

    One error of a problem document. Members beyond these describe this error further (for example dependencies on not_ready).

  • ProblemField — required: field, code, detail
  • Project — required: id, revision, status, email, used_bytes, reserved_bytes, screen_count, content_limit_bytes, screen_limit, credit_remaining, created_at, updated_at, name
  • ProjectBillingUsage — required: period, usage, stored_bytes, allowance
  • ProjectCapabilities — required: project_id, plan_id, features, feature_revision, capabilities, media_video_bytes, plan_features, limits
  • ProjectContext — required: project, organization
  • ProjectContextList — required: projects
  • ProjectCreate — required: name
  • ProjectDeleteConfirmation — required: name, revision
  • ProjectDeletionPreview — required: project, organization, devices, allowed
  • ProjectFeatures — required: advertiser, screens
  • ProjectMove — required: organization_id
  • ProjectMoveDestinations — required: organizations
  • ProjectName — required: none

    Trimmed printable project name. Rejects controls, URL-looking text, @, www., and ://.

  • ProjectOwnerTransfer — required: user_id
  • ProjectPatch — required: name
  • ProjectPlanFeature — required: id, enabled, required_plan
  • ProjectPlanFeatures — required: featuresets, features

    The plan features the project has. The plan and the project's featuresets decide them; credit never unlocks one. A feature the project does not have is refused with feature_not_in_plan (402), whose required_plan names the lowest generally sold plan that includes it.

  • ProjectPlanLimits — required: screens, members, video_bytes, event_retention_days

    The project's limits as its plan and featuresets give them, the figures admission enforces. Zero is no plan cap.

  • ProjectUptime — required: items
  • ProvisionScreen — required: none
  • RTSPStreamSource — required: protocol, url
  • ReadyResponse — required: status, degraded
  • ReleaseLaunch — required: launch_url, expires_at
  • Report — required: kind, title, generated_at, columns, rows, truncated

    One report as a table: columns says what each row member is. Rows carry more members than the columns show (ids, parent_id and depth for a folder outline). Percent columns hold 0 to 100.

  • ReportCatalog — required: items, formats
  • ReportColumn — required: key, label, type
  • ReportKindInfo — required: kind, title, description, params
  • ReportParam — required: name, description
  • ReportSchedule — required: cadence
  • ReportSubscription — required: id, name, kind, filters, schedule, format, enabled, recipients, revision, created_at, updated_at
  • ReportSubscriptionList — required: items
  • ReportSubscriptionPatch — required: none
  • ReportSubscriptionRecipient — required: user_id
  • ReportSubscriptionWrite — required: name, kind, schedule, format, recipients
  • Reseller — required: id, name, spread_bps, spread_effective_at, customer_count, review_state, customer_limit
  • ResellerCustomer — required: organization_id, name, plan_id, delegated_at, project_count, screen_count, stored_bytes, annual_list_cents, annual_wholesale_cents
  • ResellerCustomerPage — required: items, next_cursor
  • ResellerCustomerProject — required: id, name, status, screen_count, member
  • ResellerCustomerProjectPage — required: projects, next_cursor
  • ResellerEnrollment — required: organization_id
  • ResellerList — required: items
  • ResellerStatement — required: reseller_id, name, period, spread_bps, lines, usage_list_mcr, usage_wholesale_mcr, plan_annual_list_cents, plan_annual_wholesale_cents
  • ResellerStatementLine — required: organization_id, name, plan_id, delegated_from, project_count, screen_count, stored_bytes, api_events, usage_list_mcr, usage_wholesale_mcr, plan_annual_list_cents, plan_annual_wholesale_cents
  • ResellerSummary — required: id, name
  • Review — required: id, kind, state, subject, proposer, url, created_at, updated_at, impact
  • ReviewAdCreative — required: creative_id, creative_revision, content_path
  • ReviewApproveRequest — required: none
  • ReviewBlocker — required: id, state, subject
  • ReviewChangesRequest — required: note
  • ReviewDecider — required: none
  • ReviewDecisionResult — required: review
  • ReviewDependentResult — required: id, state
  • ReviewImpact — required: screens
  • ReviewList — required: items, next_cursor, pending_count
  • ReviewLocation — required: project_id, project_name
  • ReviewMediaChange — required: media_id, filename, before, after

    The pending change of one media item a selector_refresh review asks about.

  • ReviewMediaFields — required: tags, folder_id
  • ReviewMediaFile — required: sha256, bytes, content_type
  • ReviewMediaPlaylist — required: id, name, screens, media_added, media_removed
  • ReviewMediaReplace — required: media_id, filename, source, version, before, after, aspect_changed, playlists

    The replacement of one media item's file a media_replace review asks about. The media keeps its file until approval.

  • ReviewPageEdit — required: op, page_id
  • ReviewPending — required: status, review

    A review-class write under Propose access, or a write that reaches a protected screen at any access level. The change is not on glass until a person approves the review; a protected one is decided by a second approver (docs/screen-scope.md).

  • ReviewPerson — required: user_id, name
  • ReviewPlaylistChange — required: operation, base_revision, proposed, diff
  • ReviewPlaylistDiff — required: name_changed, pages_added, pages_removed, pages_changed, soundtrack_changed, media_added, media_removed
  • ReviewPolicy — required: agent_changes_require_review, review_policy_revision
  • ReviewPolicyUpdate — required: agent_changes_require_review
  • ReviewPreview — required: live, proposed

    Live and proposed playlists in the stored shape GET /api/playlists/{id} returns (pages with resolved_media).

  • ReviewProposer — required: kind
  • ReviewProtectedCampaign — required: none

    A campaign_create, campaign_update or campaign_delete.

  • ReviewProtectedChange — required: subkind

    The stored input of a protected_change review, applied through the owning service when a second approver approves. Exactly one of campaign, folder and move is present, as subkind names. Approval replays at base_revision; a campaign or folder that moved on makes the review stale (review_stale).

  • ReviewProtectedFolder — required: none

    A folder_create, folder_update, folder_delete or folder_unprotect.

  • ReviewProtectedMove — required: folder_id, screen_ids, folder_ids

    A screens_move, the body of POST /api/screens/move.

  • ReviewRejectRequest — required: reason
  • ReviewScreenChange — required: action, screens, request, playlist_ids
  • ReviewSubject — required: type, id, name
  • ReviewSummary — required: id, kind, state, url, subject, impact
  • RuntimeAdslotCandidate — required: page_id, occurrence_id, check_sequence, earliest_start_at
  • RuntimeAdslotEvent — required: event_id, decision_id, occurrence_id, kind, client_sequence
  • RuntimeAdslotEventBatch — required: events
  • RuntimeAdslotEventResponse — required: results
  • RuntimeAdslotEventResult — required: event_id, state
  • RuntimeAdslotMedia — required: kind, duration_ms, content_type, bytes, sha256, content_path, fit
  • RuntimeAdslotPage — required: id, type, adslot_id

    Whole-page advertising slot, sent only to a paired session granted adslot-v1. A Player that meets an unknown page type drops that page.

  • RuntimeAdslotResolveRequest — required: manifest_revision, candidates
  • RuntimeAdslotResolveResponse — required: server_time, results
  • RuntimeAdslotResult — required: occurrence_id, check_sequence, state
  • RuntimeAdvance — required: mode
  • RuntimeApplicationPackage — required: version, url, bytes, sha256, entrypoint, contentType

    Immutable normalized package built only from the independently validated application tree. Native players verify bytes and SHA-256 before atomically retaining this release for offline last-known-good restoration. The URL is an authorization-bound transport reference, not a public or durable object URL.

  • RuntimeApplicationPrimitive — required: id, primitive, applicationId, releaseId, launchUrl, origin, protocol, grantId, package, rect, layer, contentFit
  • RuntimeAudio — required: loop, volume, tracks

    Playlist soundtrack (docs/playlist-audio.md). Emitted only when the playlist has one and at least one track projected. The Player plays tracks in order, independently of the page sequencer; page changes, transitions and visibility never pause or restart it.

    Track identity is id plus mediaId plus sha256, never src, so a manifest refresh that keeps the playing track does not restart it. Effective gain is volume times the Player volume. A defective track is dropped on its own (invalid_audio_track).

  • RuntimeAudioCue — required: track, restart

    Soundtrack hint emitted on a page that authored audio_cue. When the page becomes current: if a different track is playing, or none, switch to track from its start; if track is playing, restart it only when restart is true. The sequence continues from track. A hint may be ignored. A cue that names no manifest track is dropped (invalid_audio_cue).

  • RuntimeAudioTrack — required: id, mediaId, src, sha256, bytes, contentType, durationMs, grantId
  • RuntimeCanvas — required: width, height, viewportFit, background
  • RuntimeCardPrimitive — required: id, primitive, card, major, params, rect, layer, contentFit

    A built-in card. For a Player declaring CardML capabilities, the backend selects the newest compatible published revision within the pinned major, considering retained revisions and all required features; when none qualifies it omits the card with card_unavailable diagnostics and removes empty pages.

    The Player merges the card's defaults, then params, then, when data is present, the dynamic properties of the document at GET /screen/card-data/{data} (only keys the card marks dynamic).

    A card with data stays hidden until its first document arrives and then fades in; screen.card_data_changed for the key refetches it in place. feed, when present, is fetched from the same route and passed to the card as its feed. A Player that lacks the card or its major draws nothing for it.

    A string in params or in the data document that begins with media: is a media reference, media:<id>, that the Player resolves to bytes it holds before the card draws it, and blanks when it cannot; it never passes a URL from params or data to a card. media lists the ready images params name, with the descriptors an image primitive's resolvedMedia carries, so the Player downloads and verifies them when the manifest arrives; a reference to media gone since publish is absent and the card draws its fallback.

    Media a data document names come from /media/{media_id} when the document arrives (ETag is the sha256). Card media never hold a page. The backend has already expanded a placement's {screen.name}, {screen.timezone}, {screen.field.NAME} and {screen.location} tokens for this screen, so params and data carry its own values.

  • RuntimeChrome — required: schema_version, banner

    Runtime-owned chrome (docs/player-compatibility.md §8). Readers read the members they know and ignore the rest; a banner shape a reader does not understand shows no banner.

  • RuntimeCodecs — required: none

    Server-derived RFC 6381 codec list for this exact rendition, never client-declared. It is a sibling of contentType; a Player can form a capability query as contentType followed by codecs="VALUE". A video whose codec cannot be derived is rejected at upload. The property is optional. An absent value does not mean that the codec is unsupported.

    A present value currently contains one video-track entry; the grammar permits comma-separated entries.

  • RuntimeCommandResultWrite — required: state

    The POST /screen/commands/{command_id}/result body. Unknown members are ignored (docs/player-compatibility.md §1.1).

  • RuntimeConditionReport — required: severity, code, context
  • RuntimeDisplay — required: none

    The screen's display control, evaluated on the device (docs/player-compatibility.md §6.5): the power schedule and override, the idle-dark setting and the brightness mode. Omitted when the screen has none; then the display stays on at the operator's brightness. Unknown members are ignored.

  • RuntimeHealthWrite — required: none

    The PUT /screen/health body. Every member is optional; send what the platform can measure. Unknown members are ignored and a value out of range is dropped (not refused). Integers are whole JSON numbers.

  • RuntimeHostHint — required: platform

    The optional native host hint on pairing start, pairing completion, and identity session mint. It names a device and is never authorization.

    It is read tolerantly (docs/player-compatibility.md §1.1.1): unknown members are ignored, a malformed field or capabilities entry is dropped, at most 32 capabilities are kept, and a value that is not an object or a platform outside the pattern drops the whole hint. None of these refuses the request.

    A Player still sends only the registered platform values and the members below, because a pre-contract backend refuses anything else.

  • RuntimeHostHintDevice — required: none

    Optional hardware identifiers in the native host hint. A malformed field is dropped.

  • RuntimeIframeCookie — required: name, value, domain, path, secure, httpOnly, sameSite

    One cookie of a shared browser tab, in the shape of the browser cookies API. The value is a secret.

  • RuntimeIframePrimitive — required: id, primitive, src, title, rect, layer, contentFit
  • RuntimeImagePrimitive — required: id, primitive, selector, resolvedMedia, grantId, rect, layer, contentFit
  • RuntimeImageResolvedMedia — required: mediaId, src, intrinsicSize, sha256, bytes, contentType
  • RuntimeIntrinsicSize — required: width, height
  • RuntimeKVEntry — required: application_id, key, value_base64, content_type, bytes, sha256, revision
  • RuntimeKVList — required: items
  • RuntimeKVSummary — required: application_id, key, content_type, bytes, sha256, revision
  • RuntimeKVWrite — required: value_base64
  • RuntimeKiosk — required: lock

    The kiosk lock (docs/player-compatibility.md §6.5). Emitted on every session while the screen's kiosk.lock is on and omitted otherwise. A Player that can pin itself to the screen does while lock is true and releases the pin when the member is absent or lock is false; one that cannot ignores it. Unknown members are ignored.

  • RuntimeLiveHeartbeat — required: connection

    The Player's own report. Open schema.

  • RuntimeLiveHeartbeatAnswer — required: lease_until, max_until
  • RuntimeLiveJoin — required: live_id, ice_servers, lease_until, max_until, heartbeat_ms, video

    What a Player publishes to and within what limits. Open schema.

  • RuntimeLiveJoinRequest — required: none

    Empty. The body may be omitted.

  • RuntimeLiveOffer — required: sdp

    A session description without its type, as the Player's offer and the relay's answer.

  • RuntimeLiveStopped — required: reason
  • RuntimeManifest — required: schemaVersion, manifestRevision, grantId, contentGeneration, screenId, screenLabel, playlistRevision, generatedAt, pages

    Immutable runtime manifest using the deterministic screenrig.canvas/v1 canvas, rectangle, fit, and source-order contract. Read-side additional properties are permitted so a player on this contract ignores unknown keys (compatibility rule 2). Write schemas stay closed.

    Pages are ordinary canvas pages and, for a paired session granted adslot-v1, whole-page adslot pages; a manifest with no adslot page is house content.

  • RuntimeManifestDiagnostic — required: level, code, detail

    One fail-safe runtime projection omission. Players and the CLI may show these; they are never authorization.

  • RuntimeMediaSelector — required: none
  • RuntimeMediaSelectorByAll — required: by, oneAtATime
  • RuntimeMediaSelectorByID — required: by, mediaId, oneAtATime
  • RuntimeMediaSelectorByIDs — required: by, mediaIds, oneAtATime
  • RuntimeMediaSelectorByTag — required: by, oneAtATime
  • RuntimeObservationSurfaceWrite — required: id, width, height, pixel_ratio, presentation
  • RuntimeObservationWrite — required: observed_at, surfaces

    The PUT /screen/observation body. Unknown members are ignored (docs/player-compatibility.md §1.1). The stored value is the project ScreenObservation.

  • RuntimeOrigins — required: content

    The delivered origin allowlist (docs/player-compatibility.md §2.3). Present on a mint response only for a Player granted origins-v1.

    The Player unions content with its compiled content origins and ignores an invalid entry. release_suffix replaces the compiled release suffix only when it is a valid DNS suffix of at least two labels; it is absent when the runtime origin serves releases itself (local development).

    The delivered set never changes the credential origin, and the backend never puts a URL on an origin this session's mint did not deliver. A Player stores the object it validated last-known-good under, so a later session without origins keeps that LKG valid.

  • RuntimePage — required: contractVersion, id, canvas, transition, advance, primitives
  • RuntimePairingScreen — required: id, public_id, label, state, revision, manifest_revision, content_access_generation, created_at, updated_at

    Runtime-owned screen summary in pairing and browser provisioning completions. Its member set is frozen: project Screen fields never appear here (docs/player-compatibility.md §8). state stays within the three values below.

  • RuntimePrimitive — required: none
  • RuntimeProblem — required: type, title, status, detail, instance, code, request_id, errors

    The problem document of the Player-facing screen (/screen/) and media (/media/) routes, the pairing streams and the probe routes (/.ready, /.health): every member flat at the top level. Store-released Players read its top-level code and action (docs/player-compatibility.md §5), so this shape stays as it is; every other route answers Problem.

  • RuntimeRect — required: x, y, width, height
  • RuntimeReport — required: none

    Report bodies and contexts are read tolerantly (docs/player-compatibility.md §1.1). A code needs its own context members; other members are ignored. Players still send only the members below, because a pre-contract backend refuses any other.

  • RuntimeScreenLabel — required: screen_label

    The stored screen name, the value the manifest carries as screen_label.

  • RuntimeScreenLabelWrite — required: screen_label

    The PUT /screen/screen-label body. The server trims screen_label and stores 1 to 120 characters without control characters. Unknown members are ignored (docs/player-compatibility.md §1.1).

  • RuntimeScreenPlaylist — required: playlist_id

    The screen's assigned playlist after the change.

  • RuntimeScreenPlaylistWrite — required: playlist_id

    The PUT /screen/playlist body. Unknown members are ignored (docs/player-compatibility.md §1.1).

  • RuntimeScreenPlaylists — required: playlists, more

    The playlists a screen's on-device picker offers, alphabetical by name without regard to case, then by id.

  • RuntimeSelectorPlaylistSnapshot — required: selections, pageMaxMs

    One stack playlist's selections, named by that playlist's own page ids.

  • RuntimeSelectorSnapshot — required: manifestRevision, snapshotRevision, selections, pageMaxMs
  • RuntimeSession — required: paired, capabilities, event_cursor, public_url

    Runtime-owned session (docs/player-compatibility.md §8). Readers ignore unknown members and unknown capabilities values. A new member is sent only to sessions whose grants cover it.

  • RuntimeSessionRequest — required: public_id

    Anonymous viewer mint. Unknown members are ignored (docs/player-compatibility.md §1.1).

  • RuntimeStack — required: levels, playlists

    Every level of the screen's stack, sent only to a Player that declared the schedule.stack host capability and only when the stack has more than one level (docs/player-compatibility.md §6.11). The manifest's root members are the bottom level's playlist; the Player resolves the levels itself with the schedule contract.

  • RuntimeStackPlaylist — required: playlistRevision, pages
  • RuntimeStatusWrite — required: observed_at, chip

    The PUT /screen/status body. Unknown members are ignored (docs/player-compatibility.md §1.1). The stored value is the project ScreenStatus.

  • RuntimeStorageWrite — required: observed_at, volume, cache, durability, plan, transfer_24h

    The PUT /screen/storage body. Unknown members are ignored (docs/player-compatibility.md §1.1). The stored value is the project ScreenStorage plus server received_at.

  • RuntimeStreamPrimitive — required: id, primitive, sources, muted, fallback, grantId, rect, layer, contentFit
  • RuntimeSuspension — required: message, since

    Emitted while the screen is suspended (docs/player-compatibility.md §6.9): pages is [] with no diagnostics, and a Player shows message as a full-screen notice instead of the no-content surface. since is when the screen was first suspended. The manifest revision is the notice's own, never a playlist's, and the screen needs no assigned playlist.

  • RuntimeTelemetryBatch — required: telemetry_epoch, stream_id, sequence, created_at, reports

    A durable FIFO Player queue sends at most one ordinary batch per minute with a randomized phase, or earlier when full. Total JSON body is at most 256 KiB; at most 64 reports, each at most 32 KiB. Every report retains its occurrence timestamp and stable play_id.

    Keep one immutable in-flight batch on disk until 202, increment sequence only after acknowledgement, and retry the same bytes after lost replies or restarts. Sequence starts at 1 and has no gaps.

    Dedupe retains at most eight live streams per screen, each watermark for at least the 24 hours in which its batch can still be replayed; keep the same stream through credential renewal. Records expire locally after 24 hours with explicit accounting. manifest.activated and manifest.upgrade stay individual and immediate.

    Interactive writes, ad resolution, content fetches, screenshots, and SDK emitConfirmed() also stay immediate. Health sampling retains its fifteen-minute cadence; urgent display/health transitions are sent immediately. Observation and ordinary health snapshots are latest-wins with original occurrence times. Health requires health.write.

    Existing individual reports remain accepted. Report item abuse limits apply per new item rather than per HTTP envelope; committed replay consumes only request admission.

  • RuntimeTransition — required: type, durationMs

    Authored page transition. Plain moves retain type, duration and optional decorations. Stinger carries the normal card content shape above both layers. Missing code or an incompatible Player interpreter degrades only the transition to crossfade of the same duration, with transition_unavailable diagnostics.

  • RuntimeTransitionCard — required: primitive, card, major, params, version, src, sha256, model, requires

    The same projected card content as a canvas card, without canvas placement geometry. Stinger is pinned to major 1; params includes durationMs and hangMs.

  • RuntimeUpgradeNotice — required: state, player_kind, recommended

    Present on a mint response when the player's comparable version is below the recommended version for player_kind (docs/player-compatibility.md §6.1). The Player starts a platform update check and shows nothing on glass. A reader ignores the member for a state it does not know.

  • RuntimeVerbosity — required: none

    The lowest log level and toast level the Player generates and shows (docs/player-compatibility.md §6.12). Emitted on every session when the screen sets either; each member is omitted when unset. Errors are always generated and shown. A Player ignores an unknown member or value and keeps its default.

  • RuntimeVideoPrimitive — required: id, primitive, selector, resolvedMedia, muted, loop, grantId, rect, layer, contentFit
  • RuntimeVideoResolvedMedia — required: mediaId, src, intrinsicSize, sha256, bytes, contentType
  • RuntimeWall — required: outputs, arrangement, rotation, span

    The screen's video wall as its Player lays it out (docs/player-compatibility.md §6.8). Emitted only when the screen has a wall. Unknown members are ignored.

  • SCIMError — required: schemas, status

    The RFC 7644 section 3.12 error document.

  • SCIMEvent — required: at, action, status
  • SCIMEventList — required: events
  • SCIMGroupList — required: groups
  • SCIMGroupProjectBinding — required: binding_id, project_id, project_name, role
  • SCIMGroupSummary — required: id, display_name, member_count, bindings
  • SCIMResource — required: none

    A SCIM 2.0 document in the shape RFC 7643 and RFC 7644 give it at the route that carries it; each operation names which it is. It is a User or Group resource, a ListResponse, a PatchOp message, a ServiceProviderConfig, a ResourceType or a Schema. Members screenRIG does not use are accepted and ignored.

  • SCIMSettings — required: enabled, base_url, tokens, user_count, group_count
  • SCIMSettingsWrite — required: enabled, proof
  • SCIMToken — required: id, name, prefix, created_at
  • SCIMTokenCreate — required: name, proof
  • SCIMTokenCreated — required: id, name, prefix, created_at, token

    A SCIMToken with its secret, returned once.

  • SSODiscovery — required: sso, required, account

    How the address signs in or signs up. sso, required and provider_name are decided by the address's domain alone; account says whether a live person holds the address.

  • SSODiscoveryRequest — required: email
  • SSOErrorCode — required: none

    The stable code a single sign-in ends with when it does not complete: the value of #sso_error= in the address POST /api/sso/finish redirects to, and the code of a failed identity-provider test. no_email: the provider asserted no email address. email_unverified: it marked the address unverified. domain_not_allowed: the address is not at one of the organization's verified domains. account_exists: the address already belongs to an account with its own sign-in; the person signs in as before and links the identity from their account (intent link). managed_elsewhere: another organization manages the person. subject_mismatch: the account is linked to a different identity at the same provider. not_provisioned: nobody holds the address and the connection does not create people. sso_required: the organization requires single sign-on for the address. staff_account: a screenRIG staff account is never signed in, adopted or linked by a customer's identity provider. expired: the sign-in outlived its 10 minutes. bad_state: the sign-in's state or browser binding does not match, or it was used already. interaction_required: a silent renewal needs the person. provider_refused: the provider answered with an error. provider_unavailable: the provider could not be reached or read. verification_failed: the provider's token or assertion failed verification. deactivated: the person is deactivated.

  • SSOPolicy — required: required, break_glass_user_ids, passkey_admin_ids, policy_revision
  • SSOPolicyWrite — required: required, break_glass_user_ids, proof
  • SSOStart — required: redirect_url
  • SSOStartRequest — required: email
  • SSOTestStart — required: redirect_url
  • ScheduleCalendar — required: subject, from, to, screens, groups
  • ScheduleCalendarConflict — required: kind, level_ids
  • ScheduleCalendarGroup — required: key, screens, screen_ids, displays, levels, spans, on_screen, conflicts
  • ScheduleCalendarOnScreen — required: display, from, to
  • ScheduleCalendarSpan — required: level_id, from, to, state
  • ScheduleImportCommitted — required: preview, applied
  • ScheduleImportLevel — required: key, action, home, content, screens, priority, rows
  • ScheduleImportPreview — required: name, columns, valid, fingerprint, summary, rows, levels, removals
  • ScheduleImportRemoval — required: home
  • ScheduleImportRequest — required: rows
  • ScheduleImportResolved — required: kind, id, name
  • ScheduleImportRow — required: row, status
  • ScheduleImportRowError — required: code, message
  • ScheduleImportSummary — required: rows, rows_with_errors, levels, creates, updates, unchanged, removes, screens, playlists
  • SchedulePreview — required: gained, lost, calendar

    What a campaign or schedule write would change. gained are the screens that would carry a level of the write they do not carry now, lost those that carry one they would no longer; a level that stays on a stack changes neither and shows in calendar.

  • SchedulePreviewReach — required: count, screen_ids
  • Screen — required: id, public_id, label, revision, manifest_revision, manifest_upgrade, content_access_generation, state, online, created_at, updated_at
  • ScreenAction — required: none

    One fleet action, discriminated by type. Each member carries only its own parameters; a member of another type is an unknown field and invalid_request.

  • ScreenActionAddTags — required: type, tags

    Adds tags a screen does not already carry. A screen that would exceed 16 tags fails with invalid_request.

  • ScreenActionAssign — required: type, playlist_id
  • ScreenActionClearDisplaySchedule — required: type

    Removes each screen's display schedule; a screen without one is ok and unchanged.

  • ScreenActionClearPlaylist — required: type

    Clear each screen's own default playlist, retaining pairing and other content levels. With no effective content the Player shows its idle display. Review-class, like assign.

  • ScreenActionClearPlaylistSchedule — required: type

    Removes each screen's playlist schedule; a screen without one is ok and unchanged.

  • ScreenActionClearRebootSchedule — required: type

    Removes each screen's reboot schedule; a screen without one is ok and unchanged. Manage access only.

  • ScreenActionDisplay — required: type, power

    Same rules as ScreenDisplayWrite. until is checked against the request clock when the Idempotency-Key has no fleet record, and again by each screen.

  • ScreenActionDisplayClear — required: type

    Ends each screen's manual display override (DELETE /api/screens/{id}/display); a screen without one is ok and unchanged.

  • ScreenActionMaintenance — required: type

    POST /api/screens/{id}/clear-cache, /restart-app or /update per screen; a screen whose host did not declare the capability fails alone with command_unsupported. An offline screen holds the command queued until it comes online (expires_in_s).

  • ScreenActionReboot — required: type

    POST /api/screens/{id}/reboot per screen; a screen whose host did not declare reboot fails alone with reboot_unsupported. An offline screen holds the reboot queued until it comes online (expires_in_s).

  • ScreenActionReload — required: type

    POST /api/screens/{id}/reload per screen. An offline screen holds the reload queued until it comes online (expires_in_s).

  • ScreenActionRemoveTags — required: type, tags

    Removes the listed tags; a tag the screen does not carry is ignored.

  • ScreenActionRequest — required: selector, action
  • ScreenActionResult — required: action, matched, succeeded, failed, results
  • ScreenActionScreenResult — required: screen_id, status

    One screen's outcome. ok carries the result of the single-screen path: revision (and tags for tag actions) for assign, tag, takeover, takeover_clear, set_playlist_schedule, clear_playlist_schedule, set_reboot_schedule and clear_reboot_schedule actions, reload for reload, toast for toast. failed carries the problem that screen's own request would have answered.

  • ScreenActionSelector — required: none
  • ScreenActionSelectorFolder — required: by, folder_id

    Every active screen in the screen folder and every folder inside it, in creation order. There is no screen-count cap.

  • ScreenActionSelectorIds — required: by, screen_ids
  • ScreenActionSelectorTag — required: by, tag

    Every active screen whose tags contain tag, in creation order. There is no screen-count cap.

  • ScreenActionSetDisplaySchedule — required: type, enabled, windows

    Replaces each screen's display schedule (ScreenDisplayScheduleWrite), normalized once before fan-out. A screen without a timezone fails alone with invalid_request.

  • ScreenActionSetPlaylistSchedule — required: type, entries

    Replaces each screen's playlist schedule with the same entries (ScreenPlaylistScheduleWrite). Entry ids are assigned once before fan-out. A screen without a timezone or without a default playlist fails alone with invalid_request.

  • ScreenActionSetRebootSchedule — required: type, enabled, windows

    Replaces each screen's reboot schedule (ScreenRebootScheduleWrite), normalized once before fan-out. Manage access only. A screen without a timezone fails alone with invalid_request, and one whose Player did not declare reboot with reboot_unsupported.

  • ScreenActionSetTags — required: type, tags

    Replaces each screen's tag set; an empty array clears it.

  • ScreenActionTakeover — required: type, playlist_id

    Same rules as ScreenTakeoverWrite. until is checked against the request clock before fan-out when the Idempotency-Key has no fleet record, and again by each screen.

  • ScreenActionTakeoverClear — required: type

    Ends each screen's takeover; a screen without one is ok and unchanged.

  • ScreenActionToast — required: type, level, text

    Same level, text, and duration rules as ScreenToastWrite, validated once before fan-out.

  • ScreenCampaigns — required: screen_id, items
  • ScreenCommand — required: id, type, state, requested_at, expires_at

    One reboot, reload, clear_cache, restart_app or update asked of a screen, in Screen.commands. A command sent to an online screen is stored sent.

    One asked of an offline screen is stored queued with no runtime event; the backend appends the event, with this id and expires_at, when it applies the screen's next online transition before expires_at, and the command becomes sent.

    Each command has exactly one runtime event, so a Player cannot see it twice. expired is derived on read for a queued command past expires_at. A newer command of the same type supersedes one still queued. A sent reboot becomes done when a health report with uptime_s puts the boot after sent_at; a reload never reaches done.

    A clear_cache, restart_app or update becomes done or failed when its Player reports, with cause and detail.

  • ScreenCommandPage — required: items, next_cursor
  • ScreenCommandWrite — required: none

    The optional body of POST /api/screens/{id}/reboot, /reload, /clear-cache, /restart-app and /update. An empty body keeps the default.

  • ScreenDeviceSettingsPatch — required: none

    A change of a screen's idle-dark and brightness settings and kiosk lock (patchScreenDeviceSettings). The body names at least one of the two members and no other.

  • ScreenDisplay — required: requested, source

    Display power state. requested is what the screen should show now: the active override, else the enabled display schedule evaluated in the screen timezone, else on (source override, schedule, or default); until is when that next changes, when known. reported is the Player's latest health display (power, connected, reported_at, stale after 35 minutes). idle and brightness are the screen's display.idle and display.brightness settings (set by ScreenPatch).

    Absent when the screen has no schedule, no override, no idle or brightness setting, and no reported display.

  • ScreenDisplayBrightness — required: mode

    display.brightness: auto maps the device's ambient light to the window brightness; fixed (the default) keeps the operator's brightness. Applied by a Player that declares the host capability brightness.auto, which it declares only when the device has a light sensor.

  • ScreenDisplayIdle — required: after_s, wake

    display.idle: the glass goes dark after after_s seconds without a touch, a key or, when wake lists presence, somebody in front of the screen (the device's camera, analysed on the device; no image leaves it). A wake event lights it again at once, and the touch that wakes a dark glass is consumed.

    While the glass is dark the Player is in a display-off, as for a display schedule: it parks playback (no plays, no ads), reports display.power off in its health and resumes on wake. A display schedule or override that holds the panel off wins, and an application holding device.display wins over idle while its page is on glass.

    Applied by a Player that declares the host capability display_power.idle.

  • ScreenDisplayOverride — required: override_id, power, until, ends_at, set_at
  • ScreenDisplayPatch — required: none
  • ScreenDisplayReported — required: reported_at, stale

    The Player's latest health display report. Observed power and connectivity, independent of requested power. stale is true after 35 minutes without a report; this is context, not proof that power caused a capture failure.

  • ScreenDisplaySchedule — required: enabled, windows, updated_at
  • ScreenDisplayScheduleView — required: display_schedule
  • ScreenDisplayScheduleWrite — required: enabled, windows
  • ScreenDisplayWrite — required: power
  • ScreenEffectivePlaylist — required: id, source

    The playlist the screen's runtime manifest is built from: the takeover, else the first campaign that applies (entry_id is the campaign id), else the first matching playlist schedule entry (entry_id), else the assigned default, else the default playlist of the nearest folder holding the screen (source folder, entry_id the folder id). until is the next instant this is known to change (takeover end or the next schedule boundary within eight days), absent when nothing time-based changes it.

    The boundary worker applies a change at most 60 seconds late. A takeover or entry whose playlist cannot be shown is skipped. Absent when the screen shows no playlist.

  • ScreenExplainAt — required: instant, effective_playlist, verdicts, not_judged

    What the screen shows at instant and why, from the resolver the boundary sweep runs. The screen's takeover, playlist schedule and the project's campaigns are read as they are now, not as they were then. A campaign whose playlist is missing or unapproved is skipped, as the sweep skips it.

    On a screen whose Player resolves its own stack (schedule.stack) the verdicts read that stack, and not_judged says so (player_stack).

  • ScreenFieldsPatch — required: fields

    A change of a screen's fields (patchScreenFields). The body has no other member.

  • ScreenFolder — required: id, name, parent_id, revision, created_at, updated_at

    One screen folder. A screen sits in at most one folder (Screen.folder_id); a folder targets its screens and those of every folder inside it.

  • ScreenFolderCreate — required: name
  • ScreenFolderDeleteResult — required: levels
  • ScreenFolderList — required: items
  • ScreenFolderPatch — required: none
  • ScreenGlass — required: none

    What the backend concluded about the screen's picture from the reports it received, never from what the Player says about itself. A check that has nothing to say leaves its member absent. Read-only on the project API. Never authorization or admission. ScreenPatch cannot write it.

  • ScreenGlassChangedDetails — required: check, verdict, previous, since, evidence

    details object on a durable project-only screen.glass_changed event, appended when a glass check changes its verdict for a screen. It is not a runtime audience command and is not delivered on GET /screen/events.

    The loop_stalled condition opens on a playback verdict stalled and ends on any other; glass_blank and glass_frozen open on a picture verdict blank or frozen and end on any other.

  • ScreenHealth — required: reported_at, stale

    The latest device health report (PUT /screen/health), sanitized, with server reported_at. A member the Player did not send is absent. stale is true when reported_at is more than 35 minutes old; stale health is still shown, never deleted; archive and screen recovery clear it.

    Transitions append the project-only screen.health_changed with details.changes, a list of {change, ...}: display_disconnected, display_reconnected, display_power (from, to), temperature_high (at or above 80 °C), temperature_normal (below 75 °C again), on_battery (battery.source became none; level_percent when reported) and plugged_in (any other source again; source), crash_spike and renderer_restart_spike (the 24-hour count rose by 3 or more since the last spike event; crashes_24h or renderer_restarts_24h and previous). battery is present only when the device reports one; the backend reads nothing from it but battery.source for the on_battery condition and infers no cause.

    Read-only; never authorization.

  • ScreenHealthHistory — required: none

    A page of reports (resolution raw) or hourly summaries (resolution hour).

  • ScreenHealthHour — required: hour, reports, temperature_max_c, temperature_avg_c, cpu_load_max, memory_used_ratio_max, wifi_rssi_min_dbm, display_disconnected, crashes_24h_max, renderer_restarts_24h_max, last_reported_at

    One screen's reports in one UTC hour. A member is null when no report of the hour carried it.

  • ScreenHealthHours — required: resolution, hours, next_cursor
  • ScreenHealthSample — required: reported_at

    One stored device health report: Screen.health without stale, and without cpu.utilization_percent and cpu.app_percent, which only the latest report (Screen.health) carries. A member the Player did not send is absent.

  • ScreenHealthSamples — required: resolution, samples, next_cursor
  • ScreenIdentifyAccepted — required: identify_id, duration_ms, expires_at
  • ScreenIdentifyDetails — required: identify_id, label, screen_id, duration_ms, at, expires_at

    details object on a durable player.identify event.

  • ScreenIdentifyWrite — required: none
  • ScreenKiosk — required: lock

    kiosk.lock: the Player pins itself to the screen (Android screen pinning with startLockTask; the person at the screen confirms the first time, and status bar, home and recents are blocked while pinned; the managed flavour as device owner keeps its lock task). Present only while the lock is on.

    The operator settings panel offers Leave kiosk lock, which unpins until the next manifest or restart applies it again. Applied by a Player that declares the host capability kiosk_lock.

  • ScreenKioskPatch — required: lock
  • ScreenLevelChange — required: source, id, playlist_id, screens
  • ScreenLevelChanges — required: gained, lost

    What a write does to the schedules of the screens it changes: the campaigns whose audience they enter (gained) or leave (lost), and the folder default playlists that start or stop being their default. screens counts the affected screens per level.

    On a tag write a campaign entry reports audience membership: every live campaign the screens enter or leave, whether or not it plays there, which depends on the screen's default playlist. A move or folder change lists the campaigns whose folder audience moves on screens that play them.

  • ScreenLinkSessionRequest — required: screen_link

    The screen link secret plus the optional host, playback and player hints. Unknown members are ignored, and host, playback and player are read tolerantly (docs/player-compatibility.md §1.1). The secret is a credential: it is never logged or echoed.

  • ScreenLinkSummary — required: hint, created_at

    The screen's link, without its url. Present only while the screen has a link. Read-only; POST and DELETE /api/screens/{id}/link change it.

  • ScreenList — required: items
  • ScreenLocation — required: latitude, longitude

    Where a screen is, in decimal degrees, with an optional short place name and a street address. A card placement reads it through the {screen.location} token, and the screen list filters by distance from a point (near).

  • ScreenLocationPatch — required: location

    A change of where a screen is (patchScreenLocation). The body has no other member.

  • ScreenMaintenanceAccepted — required: command_id, command, expires_at, state
  • ScreenManifestUpgrade — required: desired_revision, active_revision, desired_playlist, active_playlist, state, code, attempt, retry_at, missing_page_count, state_since, reported_at

    Always-present computed manifest-upgrade state for this screen, derived at read time from its issued desired revision or queued shared-playlist content goal, its last server-acknowledged active manifest revision (manifest.activated), and the latest accepted manifest.upgrade report slot.

    Read-only project state: no body can write it, and no report ever promotes a grant. active_revision is the last acknowledged activation, not proof that every simultaneous session already shows it.

    Being offline never produces failure, and an overdue retry_at on a retrying state is client presentation, never a server judgment. desired_revision null is none. state pending names a desired revision with no matching report; activating names a target already on glass whose acknowledgement is still pending; a report slot whose revision stopped matching desired_revision is ignored until a new report matches, so a new desired manifest derives pending without clearing anything.

    Before the next manifest contact issues a shared edit's desired grant, the desired revision and playlist can expose that queued goal as read-only intention; it grants no access. Active identity always comes from the exact acknowledged historical grant. An older activation cannot announce the newer queued goal as current.

  • ScreenMove — required: folder_id

    At least one id across screen_ids and folder_ids, at most 1000 in all.

  • ScreenMoveResult — required: screens, folders, levels
  • ScreenNamePatch — required: name

    A screen's new name (patchScreenName). The body has no other member.

  • ScreenNotJudged — required: code, detail

    Something the explanation does not judge.

  • ScreenObservation — required: observed_at, surfaces

    Player-reported playback surface. Absent on Screen until the first accepted PUT /screen/observation. Read-only on the project API; ScreenPatch, PairScreen, pairing bodies, session bodies, canvas, runtime manifest, and POST /screen/reports cannot write it.

  • ScreenObservationSurface — required: id, width, height, pixel_ratio, presentation
  • ScreenOutage — required: offline_since

    The screen's latest presence outage and, once the first health report after the screen is back decides it, why the screen was gone. A new outage replaces it; a screen that has never been offline since outages were recorded has none.

    The cause comes from the Player's own uptime counters in that report, read against the outage and never against the device clock: device_restart (the device started after the outage began), app_crash (the Player started and its 24-hour crash count rose), app_restart (the Player started and the device did not), network (neither started, and nothing points at screenRIG) and platform (neither started, and a player.stream_down report reached screenRIG during the outage, or the presence observer was down or recovering when the screen fell silent). likely_cause is absent when unknown, and it stays unknown rather than guess: a report without uptimes, one that is too close to the start of the outage, a restart that came after the screen was back, and a Player report within a minute of the reconnect decide nothing.

    A report decides only within 35 minutes of the screen coming back. device_restart cannot tell power loss from a reboot, and network cannot tell the screen's own network from its upstream.

    Deciding it appends the project-only event screen.outage_classified once, with details {offline_since, back_at, likely_cause, evidence, online_event_id}; the resolved notification of an offline screen names the cause when it is decided by the time the notice goes out. Readers treat a likely_cause they do not know as unknown. Read-only; never authorization.

  • ScreenPatch — required: none
  • ScreenPlayPageAccepted — required: screen_id, playlist_id, page_id, manifest_revision, expires_at
  • ScreenPlayPageDetails — required: page_id, playlist_id, manifest_revision, expires_at

    details object on a durable player.play_page event.

  • ScreenPlayPageWrite — required: page_id
  • ScreenPlayerIdentity — required: legacy, seen_at

    Asserted identity from the latest paired runtime mint. Read-only display metadata, never authorization. Internal grants and mint fields are withheld.

  • ScreenPlaylistPatch — required: playlist_id

    An assignment of a screen's playlist (patchScreenPlaylist). The body has no other member.

  • ScreenPlaylistSchedule — required: entries, updated_at

    Server-evaluated playlist schedule. It never reaches the runtime manifest; the manifest is built from the effective playlist it selects. Write it with PUT /api/screens/{id}/playlist-schedule.

  • ScreenPlaylistScheduleView — required: entries
  • ScreenPlaylistScheduleWrite — required: entries
  • ScreenPresenceHistory — required: items, next_cursor
  • ScreenPresenceTransition — required: at, state
  • ScreenProvisioning — required: screen, public_url, provisioning_url, expires_at
  • ScreenRebootAccepted — required: reboot_id, expires_at, state
  • ScreenRebootSchedule — required: enabled, windows, updated_at

    The windows in which the backend reboots the screen. Present while one is set.

  • ScreenRebootScheduleView — required: reboot_schedule, next_reboot_at
  • ScreenRebootScheduleWrite — required: enabled, windows
  • ScreenRecoveryHost — required: none

    What the device asking to recover this screen says it is, copied from the pairing start's host object. Descriptive fields only; it never carries duid, serial, or mac. Absent fields were not reported.

  • ScreenRecoveryPending — required: expires_at

    Present while a native pairing session that presented this screen's hardware identity is waiting for the owning project to confirm with POST /api/screens/{id}/recovery/confirm. Carries the deadline, which is the pairing session's own expiry, and the offering device's descriptive host fields (never duid, serial, or mac).

    A DUID is readable by any application on the panel, so an offer is a phishing surface: compare host.model and host.firmware with the display in front of you before confirming.

    The server refuses an offer while the screen's bound key has shown life within the last ten minutes (session mint, runtime stream, manifest fetch, or presence heartbeat), and accepts at most three offers per screen per rolling hour; a new offer replaces the pending one. Absent once confirmed, lapsed, or claimed as a new screen. Read-only.

  • ScreenReloadAccepted — required: reload_id, expires_at, state
  • ScreenReplaceWrite — required: with
  • ScreenScheduleEntry — required: id, playlist_id
  • ScreenScheduleEntryWrite — required: playlist_id

    One playlist schedule entry, a level of the screen's own stack (packages/schedule-contract SEMANTICS.md, Levels and the stack). id is optional (entry_N is assigned in order when omitted) and unique in the schedule.

    It holds while all its rule members hold: from (inclusive) and until (exclusive), civil minute-precision bounds with no offset; an occurrence of windows, monthly or dates (none of the three recurs every day) whose date is not in except; data, a card-data condition; interaction, while someone is using the screen.

    An entry sets at least one rule member. data, interaction, covers and a displays lock that leaves outputs out are honored by a Player that resolves its own stack; the server's resolution for other Players skips such an entry (stack_only).

  • ScreenSchedulePreviewRequest — required: entries
  • ScreenScheduleRevision — required: revision, created_at, change, current, entries

    One stored revision of a screen's playlist schedule: its whole entries list after a write (no entries: the screen had no schedule). revision is the screen's revision at the write. change is edited, restored (a copy of an earlier revision, named by restored_from) or baseline (the schedule the screen held when its history began).

  • ScreenScheduleRevisionList — required: items
  • ScreenScheduleWindow — required: days

    One screenrig.schedule/v1 window in the screen timezone. days are stored mon-to-sun. Omit start and end for the whole day. end <= start crosses midnight and the start day owns it (fri 22:00-02:00 runs into Saturday morning); equal edges run a full 24 hours.

  • ScreenScope — required: folder_ids, screen_ids

    What a scoped member or agent may act on (docs/screen-scope.md): the screens in the listed screen folders and in every folder inside them, and the listed screens. At least one id in all. An id that names no live folder or screen of the project when written is invalid_request at its position; a later deletion leaves a dead id, which grants nothing.

    The scope is read on each request, so a change applies to the next one. Tags are never scope.

  • ScreenScreenshotAccepted — required: capture_id, expires_at
  • ScreenScreenshotFailedDetails — required: capture_id, reason

    details object on a durable screen.screenshot_failed event.

  • ScreenScreenshotReadyDetails — required: capture_id, bytes, width, height, sha256

    details object on a durable screen.screenshot_ready event. Pixels and object keys are not present.

  • ScreenScreenshotRequestedDetails — required: capture_id, expires_at, max_width_divisor, max_height_divisor, format, quality, max_bytes

    details object on a durable screen.screenshot_requested event. Image bytes and object keys are not present.

  • ScreenScreenshotStatus — required: state
  • ScreenStackStatus — required: manifest_revision, levels, playing, reported_at

    What the screen's Player last reported of its stack (docs/player-compatibility.md §6.11): each level's readiness and the level each display shows in each region (the page and any strip). Present only for a Player that resolves its own stack, while that stack is current.

  • ScreenStatus — required: chip, observed_at, received_at

    The status chip the screen's Player last reported with PUT /screen/status (docs/player-compatibility.md §9.5): the screenrig.overlay/v1 condition that wins its rank, or null when the Player shows no chip. Absent until the first accepted report. Cleared on identity reset, unpair, and archive.

    It is the Player's last report, so consumers treat it as stale when the screen is not online (Screen.online), like every Player report. level and icon come from the backend's catalogue for chip, never from the Player, and are absent when chip is null. Read-only on the project API. Never authorization or admission. ScreenPatch cannot write it.

  • ScreenStatusChangedDetails — required: chip

    details object on a durable project-only screen.status_changed event, appended when PUT /screen/status changes the stored chip, level or icon. level and icon are absent when chip is null. This type is not a runtime audience command and is not delivered on GET /screen/events.

  • ScreenStorage — required: observed_at, received_at, volume, cache, durability, plan, transfer_24h

    Sanitized player storage report. Absent until the first accepted PUT /screen/storage. Cleared on identity reset, unpair, and archive. Consumers treat received_at older than 24 hours as stale. Read-only on the project API. Never authorization or admission. ScreenPatch cannot write it.

  • ScreenStorageCache — required: house_used_bytes, capacity_bytes, reserve_bytes, protected_bytes, fallback_bytes, warm_bytes, ad_headroom_bytes
  • ScreenStorageExcludedPage — required: page_id, reason
  • ScreenStorageForecast — required: manifest_revision, fit, excluded_page_count, basis, received_at

    Approximate steady-state target selection (plan A.3 only, no transition) from the last reported capacity and the screen's desired manifest. Absent without a storage report, which consumers read as unknown. basis is reported_capacity. Recomputed when a storage report arrives and when the screen's manifest revision changes. Never authorization or admission.

  • ScreenStorageForecastDryRun — required: fit, excluded_page_count, required_bytes, capacity_bytes, basis, received_at

    Pre-assignment fit dry run for one playlist. fit, excluded_page_count, and required_bytes come from plan A.3 target selection against the screen's last reported capacity (basis reported_capacity); there is no transition prediction and nothing is treated as local. required_bytes is the retained cost of every page of the playlist. fit unknown means the screen has no storage report, or the playlist's content references are not ready; required_bytes, capacity_bytes, and received_at are null then. received_at is the storage report's receipt time, and a report older than 24 hours is stale but still forecast from, exactly like Screen.storage_forecast.

    It is read-only metadata and never authorization or admission.

  • ScreenStorageForecastRequest — required: playlist_id

    Body of the pre-assignment fit dry run. playlist_id must be a playlist of the authenticated project; another project's or an unknown id is not_found.

  • ScreenStoragePlan — required: manifest_revision, fit, transition, required_bytes, target_bytes, excluded_pages
  • ScreenStorageShortfall — required: at, fit, required_bytes, capacity_bytes, excluded_page_count

    Present while the player's reported fit is partial, transition_blocked, or none_fit, except a transition_blocked plan whose only blocking reason is anchor_unavailable: that is a failed download on a device with room, not a shortfall. at is when the condition began.

    It is set once when the condition begins and removed when it ends, each transition appending one project-only event, screen.storage_shortfall or screen.storage_shortfall_cleared. Those events are not delivered on GET /screen/events. Cleared with Screen.storage on identity reset, unpair, and archive.

    Read-only project health metadata; it does not change screen revision or manifest authority and is never authorization.

  • ScreenStorageTransfer — required: new, refetch, repair, failed
  • ScreenStorageVolume — required: total_bytes, available_bytes
  • ScreenSurfaceChangedDetails — required: observed_at, surfaces

    details object on a durable screen.surface_changed project event. Pixels are not present. This type is not a runtime audience command and is not delivered on GET /screen/events.

  • ScreenSuspendWrite — required: message
  • ScreenSuspension — required: message, since

    Present while the screen is suspended (docs/player-compatibility.md §6.9). The runtime manifest carries the same object as its suspension member.

  • ScreenTags — required: none

    Fleet selector tags, 0 to 16 unique exact tags, each matching the media tag grammar. On ScreenPatch the array replaces the whole set and an empty array clears it; a duplicate or malformed tag is invalid_request. Changing tags bumps the screen revision (If-Match guards it) and appends screen.updated with details.tags; it never changes the manifest revision.

    Tags are never on the runtime manifest and never authorization.

  • ScreenTagsPatch — required: tags

    A screen's complete new tag set (patchScreenTags). The array replaces every tag the screen carries and an empty array clears them. The body has no other member.

  • ScreenTakeover — required: playlist_id, until, set_at

    The playlist that wins over campaigns, the schedule and the assignment until until, or until cleared when until is null.

  • ScreenTakeoverWrite — required: playlist_id
  • ScreenTimelineSegment — required: from, to, source
  • ScreenToastAccepted — required: expires_at
  • ScreenToastDetails — required: level, text, duration_ms, expires_at

    details object on a durable screen.toast event. Colours are not present.

  • ScreenToastWrite — required: level, text
  • ScreenUptime — required: items
  • ScreenVerbosityPatch — required: none

    A change of a screen's log level and toast level (patchScreenVerbosity). The body names at least one of the two members and no other.

  • ScreenVerdict — required: kind, playlist_id, verdict

    One candidate at the explained instant. won: the resolver picks it (on a screen whose Player resolves its own stack: it fills its region on a display it targets). outranked: it holds, and by is the candidate that won. not_started: before its from. ended: at or after its until (a takeover: its end). outside_hours: inside from and until, outside its windows. conditional: on a screen whose Player resolves its own stack, it holds by time and plays while what only the Player observes holds too (reason interaction or data). off: it does not apply, and reason says why.

  • ScreenWall — required: outputs, arrangement

    The video wall a screen's Player lays out: two to twelve outputs that show one canvas. Setting it needs a Player that declared the display.wall host capability (docs/player-compatibility.md §6.5, §6.8). A playlist with a format spans it.

  • ScreenshotCaptureID — required: none

    Optional stage_, qa_, or development_ prefix, then shot_ and a random suffix. New suffixes use 16 alphanumeric characters excluding oOlL; retained legacy suffixes are accepted.

  • SelectorPreview — required: primitive, selector, matched_count, candidates
  • SelectorPreviewInput — required: primitive, selector
  • SelectorPreviewMedia — required: media_id, filename, tags
  • ServiceClient — required: id, project_id, name, capabilities, access, state, created_by, keys, secrets, created_at, updated_at, authenticated_requests, tokens_issued
  • ServiceClientChange — required: none
  • ServiceClientKey — required: kid, alg, thumbprint, jwk, added_at
  • ServiceClientList — required: items
  • ServiceClientResult — required: client
  • ServiceClientSecret — required: id, hint, added_at
  • SessionDescription — required: type, sdp
  • SessionSSOStartRequest — required: intent
  • SignInPolicy — required: password, passkey, passkey_enrollment_required, policy_revision, federated

    Verified person sign-in policy. Passive defaults preserve local sign-in. An enforced organization policy directs sign-in through its identity provider.

  • SignInResetAccepted — required: status

    Identical for known and unknown addresses; no address, credential, project, or delivery status is returned.

  • SignInResetRequest — required: email
  • SignupCreated — required: user_id, project_id, organization_id
  • SignupHeardDetail — required: none

    The follow-up to heard. kind names a choice from a short list, and text is free text.

  • SignupPasskeyOptionsRequest — required: email, display_name
  • SignupProfile — required: none

    The answers a person gives after signing up. Every member is optional and may be null, meaning unanswered or skipped.

  • SignupRequest — required: email, display_name, marketing_email, credential

    The email address and display name are those the ceremony was started with.

  • Source — required: id, name, kind, target, enabled, config, preset, settings, secrets, refresh_seconds, stale_after_seconds, revision, status, created_at, updated_at
  • SourceArea — required: key, name, rooms, status, screens
  • SourceCreate — required: name, target

    JSON, CSV and Sheets config may set key_template, a card data key with {screen.field.NAME} tokens. Its mapping then produces {documents:[{fields:{NAME:VALUE},document:{...}}]} instead of one document. Each output is validated against the target card.

    Keys are unique and outside card-instance and feed namespaces; source test previews the envelope and validates every output. Each key uses the source stale period. Missing keys are retained with their existing expiry; storage failures can leave partial writes and the next run retries.

  • SourceError — required: code, message, at
  • SourceKind — required: none

    Where the data comes from. ics reads iCalendar and webcal:// addresses (the other kinds are described in /docs/sources). A kind that is not available answers invalid_request at kind.

  • SourceList — required: items, next_cursor
  • SourcePreset — required: name, title, category, description, kind, cards, fields, secrets, refresh_seconds, min_refresh_seconds, stale_after_seconds, attribution, docs

    A ready-made, tested configuration of the json data source.

  • SourcePresetAttribution — required: text
  • SourcePresetCard — required: type, default
  • SourcePresetField — required: name, label, type, required, help

    One thing a person tells a preset. A text is checked against pattern and max_length, a choice is one of options, and a list holds min_items to max_items objects filled in with fields.

  • SourcePresetList — required: items
  • SourcePresetOption — required: value, label
  • SourcePresetSecret — required: name, label, help, how_to_get, required

    A credential a preset needs, entered under name in secrets.

  • SourceRoom — required: key, status, screens
  • SourceRoomRef — required: id, name
  • SourceRoomScreen — required: id, name, kind, field, value, status
  • SourceRooms — required: source_id, room_field, room_key_prefix, area_field, area_key_prefix, rooms_as_of, summary, rooms, areas, screens, warnings

    The room mapping of a data source that writes a document for each room or area: the rooms the source offered at its last good refresh against the screens that read them.

    A screen belongs to the report for a field when it has a value for it, or when its own playlist places a card whose data key is the key prefix followed by {screen.field.NAME}; a playlist it reaches through a folder, campaign or schedule level is not followed.

  • SourceRoomsSummary — required: rooms, unmapped_rooms, areas, unmapped_areas, screens, missing_screens, unknown_screens
  • SourceSecretView — required: set, hint, updated_at
  • SourceStaleAfter — required: none

    How long the card keeps the source's last good data when it cannot refresh, in seconds.

    The source writes its documents to expire that long after the last good refresh, so when it keeps failing they blank on every screen (offline ones included) and pages whose visibility depends on the data fall back to the pages after them; a source that is not failing renews the deadline as it refreshes.

    At least twice refresh_seconds. null keeps the last good data until the source refreshes again (the default for every kind but momentus, whose default is 1800 when the member is omitted on create). A failing source that passes the period is stale (status.stale) and appends source.stale.

  • SourceStatus — required: state, last_attempt_at, last_success_at, last_change_at, next_run_at, failures, stale, data_expires_at, error, warnings, stats

    What the last runs did. state is pending (not run yet), ok (the last fetch succeeded and the card accepted the document), error (the last run failed and the card kept its last good document) or disabled. ok does not judge whether the upstream data is right or current, nor whether any screen shows the card.

  • SourceTarget — required: card_id
  • SourceTestRequest — required: none
  • SourceTestResult — required: document, valid, warnings, stats, fetched_at
  • SourceUpdate — required: none
  • StackLevel — required: id, source, playlist_id

    One level of a screen's stack (packages/schedule-contract SEMANTICS.md, Levels and the stack). id is takeover, campaign:ID, schedule:ENTRY_ID, default, or folder:FOLDER_ID; record_id names the campaign, entry or folder, name the campaign's or folder's name. rule absent always holds.

  • StackLevelRule — required: none
  • StreamSource — required: none
  • StreamSourceWrite — required: none

    A stream source. A source may give only its url and let the scheme name the protocol: https is hls, rtsp and rtsps are rtsp.

  • SupportConversation — required: id, subject, created_at, updated_at, last_sequence, human_requested, unread_staff, closed
  • SupportConversationList — required: items, next, unread_staff_total
  • SupportHours — required: timezone, start, end, weekdays, excludes_bc_holidays
  • SupportMessage — required: id, conversation_id, sequence, role, author, body, created_at
  • SupportMessageList — required: items
  • SupportRead — required: sequence
  • SupportStatus — required: chat_allowed, available, staffed, human_available, hours, human_wait_seconds, docs_url
  • SupportSubmission — required: conversation, message
  • SupportWrite — required: body
  • TabShare — required: id, until, screens, skipped, warnings
  • TabShareCookie — required: name, value, domain

    One cookie in the shape of the browser cookies API. The value is a secret.

  • TabShareScreen — required: id, label
  • TabShareSkip — required: id, label, code, detail

    A target that was not taken over. code is the problem code taking that screen over on its own would answer.

  • TabShareState — required: id, until, screens
  • TabShareStopped — required: id, screens
  • TabShareWarning — required: code, url, detail
  • TabShareWrite — required: tabs

    The tabs to show and the screens to show them on. At least one of screen_ids, folder_ids and tags.

  • Trigger — required: id, kind, label, target, default_for_seconds, url, username, revision, created_at, updated_at

    A CAP alert trigger or an overlay trigger. Its password is returned only by create and rotate-secret.

  • TriggerAlert — required: id, revision, state, status, msg_type, sender, identifier, until, screens, started_at, updated_at

    The trigger's latest alert, from the CAP message fields.

  • TriggerAlertScreens — required: targeted, taken_over, cleared, skipped, failed, pending

    What the latest takeover change did. skipped counts screens without a default playlist, archived or gone, and, when clearing, screens another takeover has replaced since.

    A screen in a protected screen folder is left as it is and counted in protected, not skipped; ending an alert (cancel, all clear, an operator clear) still clears what the trigger set on such a screen.

  • TriggerClear — required: none
  • TriggerDelivery — required: at, outcome, status, bytes, request_id
  • TriggerDeliveryList — required: items
  • TriggerList — required: items
  • TriggerOverlay — required: show, style, enabled, signing, alerts, screens, pending

    An overlay trigger's configuration and state.

  • TriggerOverlayAlert — required: id, until, started_at, updated_at, revision
  • TriggerOverlayReceipt — required: outcome, trigger_id, until, active
  • TriggerOverlayRequest — required: none

    One post to an overlay trigger, as read after the trigger's mapping (if any). A clear ignores every member but alert_id, clear and state.

  • TriggerOverlayScreens — required: targeted, holding, taken_over, removed, edge_taken, skipped, failed

    What the latest fan-out did to the target screens. A screen in a protected screen folder is left as it is and counted in protected, not skipped; ending the alert still clears what the trigger set on it.

  • TriggerOverlayStyle — required: none

    The text card's static params an overlay is drawn with. The trigger chooses the layout.

  • TriggerOverlayWrite — required: show
  • TriggerPatch — required: none
  • TriggerReceipt — required: outcome, trigger_id
  • TriggerSecretRotate — required: none
  • TriggerTarget — required: none

    Exactly one of tag and screen_ids.

  • TriggerWithPassword — required: none
  • TriggerWithSecrets — required: none
  • TriggerWrite — required: label, target
  • UDPStreamSource — required: protocol, group, port
  • URLStreamSource — required: url
  • UploadScope — required: playlist_ids, folder_ids

    What an uploader may use (docs/uploaders.md): the playlists it changes pages of and the media folders it uploads into. Folders are exactly the listed ones, never their subfolders. An id that names no live object of the project when written is invalid_request at its position; a later deletion leaves a dead id, which grants nothing.

    The scope is read on each request, so a change applies to the next one.

  • UptimeDay — required: day, online_s, offline_s, availability, coverage

    One UTC day. availability is online_s over online_s plus offline_s, null when nothing was recorded. coverage is the share of the day (of every reporting screen's day in a project row) with a recorded state, 0 to 1: a gap lowers coverage and is never offline time. intervals (screen rows) is how many recorded intervals touched the day; screens (project rows) how many screens had a recorded state; live marks a screen day that includes the open interval up to now.

  • UsageFrame — required: page_id, primitive_id, rect

    One image or video primitive that names the media file, with its frame and how the file fills it.

  • UsageScreen — required: id, label, screen, playlist_ids, how

    One active screen that uses at least one of the listed playlists.

  • UsageScreenHow — required: playlist_id, uses
  • UsageTagFilter — required: all, any, none

    A tag selector's filter. A file matches when it has every all tag, at least one any tag when any are named, and no none tag; the shorthand tag selector is all with one tag.

  • UsageTrack — required: index, id
  • UserEmailChangeAccepted — required: none
  • UserEmailChangeRequest — required: email, proof

    Requests a verified-email change using fresh proof. The current email stays effective while verification is pending. The old address receives a warning only, with no undo link.

  • VerifiedOrganizationDomain — required: domain, organization_id, state, verified_at
  • VersionResponse — required: version, commit, api_version, protocol_version
  • Webhook — required: id, url, event_types, enabled, revision, status, created_at, updated_at

    A project webhook. Player log records (runtime.reported) are not delivered.

    Each matching project event is POSTed to url as the same JSON object GET /api/events returns, with headers ScreenRig-Webhook-Id, ScreenRig-Event-Id (the event cursor, stable across retries), User-Agent, and ScreenRig-Signature t=<unix seconds>,v1=<hex HMAC-SHA256 over "<t>.<raw body>" keyed with the secret string>.

    A 2xx answer within 10 seconds succeeds; any other status, a redirect (never followed), a timeout, or a connection or TLS failure is retried with exponential backoff (30 seconds doubling to one hour, jittered) for 24 hours and then failed. After three consecutive timeouts the attempt timeout drops to 5 seconds until a response arrives.

    A webhook has at most one attempt in flight and a project at most two, across all servers. Delivery is at least once and unordered; deduplicate on ScreenRig-Event-Id.

    Each attempt is metered like a listen-stream event (1 credit after the monthly 10,000 API/SSE allowance), and the same events that are free on the listen stream are free here: screen.*, runtime.*, alert_mute.*, application.event, playback.page_failed, and agent.command.

    An attempt refused before anything is sent (url_rejected, dns_failed) is not billed. payment_required and secret_unavailable back off but never count toward failing or auto-disable. status is failing while no delivery has succeeded since failing_since; after 72 hours of continuous failure the webhook is disabled (disabled_reason delivery_failures) and notification.disabled is appended.

  • WebhookDelivery — required: id, webhook_id, event_id, event_type, state, attempts, created_at
  • WebhookDeliveryAttempt — required: attempt, at, status, error, duration_ms
  • WebhookDeliveryAttemptList — required: items
  • WebhookDeliveryList — required: items, next_cursor
  • WebhookEventTypes — required: none

    Exact event types such as screen.online, or prefixes ending in .* such as screen.* (every type starting with screen.). notification.test is never fanned out by a subscription; it is sent only by POST /api/webhooks/{id}/test.

  • WebhookHandshake — required: none

    A vendor handshake the URL answers, for a vendor with no signature scheme here. microsoft_graph answers a POST that carries a validationToken query parameter by echoing the decoded token as text/plain. monday answers a JSON POST of {"challenge": "..."} with the same JSON. trello answers its HEAD check with 200. azure_event_grid answers a SubscriptionValidationEvent (aeg-event-type: SubscriptionValidation) with {"validationResponse": "<validationCode>"}. verify.vendor slack answers Slack's signed url_verification challenge, and verify.vendor asana answers Asana's X-Hook-Secret handshake and keeps that secret to verify its events.

    A handshake is answered only for a webhook set up for that vendor, writes nothing, is never billed and spends no rate budget, and is recorded in the delivery log with outcome handshake. A disabled webhook answers none.

  • WebhookList — required: items
  • WebhookPatch — required: none
  • WebhookVerify — required: vendor, secret

    The vendor verification of a webhook or trigger, as a read shows it. The secret is only ever a hint.

  • WebhookVerifyVendor — required: none
  • WebhookVerifyWrite — required: vendor

    A vendor whose own signature authenticates a post in place of the secret, because these vendors cannot send ours.

    The header and scheme of each are the vendor's own and fixed: github sends X-Hub-Signature-256, sha256= and the hex HMAC-SHA256 of the body; stripe sends Stripe-Signature, t=<unix seconds>,v1=<hex HMAC-SHA256 of "<t>.<body>"> (several v1 while a secret is rolled, t within five minutes); shopify sends X-Shopify-Hmac-Sha256, the base64 HMAC-SHA256 of the body; slack sends X-Slack-Signature, v0= and the hex HMAC-SHA256 of "v0:<X-Slack-Request-Timestamp>:<body>" (within five minutes); linear sends Linear-Signature, the hex HMAC-SHA256 of the body, and the webhookTimestamp member of the body (Unix milliseconds) must be within a minute; vercel sends x-vercel-signature, the hex HMAC-SHA1 of the body; asana sends X-Hook-Signature, the hex HMAC-SHA256 of the body keyed by the X-Hook-Secret of Asana's handshake; generic_hmac is any sender that signs with HMAC-SHA256 in the header you name.

    A post that carries a valid signature is accepted without the secret, and the secret keeps working beside it. verify cannot be combined with signing. A post is judged on the body as it arrived, before it takes any rate budget. Slack and Asana also answer their handshakes (see WebhookHandshake).

  • WebhookWithSecret — required: id, url, event_types, enabled, revision, status, created_at, updated_at, secret

    A Webhook plus its signing secret. Returned only by create and rotate-secret.

  • WebhookWrite — required: url, event_types
  • WebsiteSetupCode — required: code, expires_at