Remote updates HTTP API PRO
Base URL: https://push.scripting.fun/v1/remote-updates. Send Authorization: Bearer <credential> and Content-Type: application/json. Dates use UTC ISO 8601; JSON fields use snake_case.
Credentials
The master key manages targets and sender keys. It cannot start, update or reload targets directly; no-new-state end cleanup is allowed. Legacy notification child keys cannot use these endpoints.
Create a sender with POST /sender-keys: targets (explicit IDs), actions (from the table below), optional created_from (start target IDs), and idempotency_key. The response contains id, credential, expires_at. Save the credential securely. created_from grants access only to activities created by that same sender. GET /sender-keys lists metadata; DELETE /sender-keys/:id revokes a key. These management operations use the master key.
You can also create and copy a scoped sender key from a target's Create Sender Key action in Remote Updates. Never put the master key in widget code or business state.
Sending
New final state requires expected_revision. Omit state to end with the last committed state. priority is normal or high; relevance_score is 0–1. Transport expiry defaults to five minutes and may be at most 24 hours in the future.
Responses and queries
Successful JSON responses are {ok:true,data,timestamp}. Sending returns HTTP 202 with {target_id,state_revision,state_committed,launch_request_id?,operation}. A snapshot contains target_id, has_state, state, revision. GET state supports ETag / If-None-Match and may return HTTP 304 without a body.
- GET
/operations/:id: operation status, pending reason, error and transport ID when available. - GET
/widget-targets,/activities,/start-targets: paginated metadata (items,next_cursor); usecursorfor the next page. Optional filters:installation_id,script_binding_id; activities also acceptbusiness_key,business_generation,lifecycle. - GET
/<collection>/:id: target metadata. Master keys may query management metadata; sender results are restricted to their scope. - PUT
/<collection>/:id/settings: master-managedexpected_revision, optionalpaused,alias(up to 128 UTF-16 units, null clears). DELETE/<collection>/:idrevokes the target. - POST
/widget-targets/batchor/activities/batch:{items:[{target_id,action,...}]}, 1–50 items. Widget actions:update/reload; activity actions:update/end. Inspect each item'sok,http_statusand receipt/error; partial success is possible. - GET
/capabilities: protocol features and limits; this does not prove device readiness.
Settings use registration_revision from target metadata as expected_revision; state writes use the snapshot’s revision. Sender creation accepts at most 100 target IDs and 100 created_from IDs.
Activity metadata may include render_report: status is notReported, snapshotBuilt or snapshotFailed; a reported result also includes stage, template_version, state_revision, received_at (Unix milliseconds), and current. Reports expire after seven days. They describe native snapshot construction, not system display or delivery. Only a native device credential can upload a report; scoped senders need activities:read-state to read it. Reports never change business state, lifecycle or quota.
Minimal test: start, update and end
Prepare the two-file receiver in the Live Activity guide. In Remote Updates, select its start target and create a sender with start, read-state, update and end actions, including activities created by this sender. Save the following as live-activity-test.mjs on your computer/server (Node.js 18+).
Set these environment variables in your terminal; use a scoped sender key, not your master key:
Run commands one at a time. After start, use status to wait for token_registration: "ready" before update or end; a committed start alone does not mean its update token has arrived. start should show “Preparing” on the receiver; update should change it to “Updated from server”; end requests immediate removal without new final state. Check the Lock Screen as well as the Dynamic Island. Keep remote-activity-test.json: requests are saved before sending, so repeating a command retries the same request. Do not delete it after a timeout. After a crash, confirm the old process exited before removing only its .lock file.
For a new update after checking/repairing the renderer, use node live-activity-test.mjs update "Retest after check". A different message is a deliberate new event; repeating the same message retains its request. Use a different SCRIPTING_REMOTE_TEST_FILE for a separate test session, and end old activities first. SCRIPTING_PUSH_BASE_URL optionally selects your configured server; the default is https://push.scripting.fun.
Limits and failures
JSON body: 64 KiB; widget state: 16 KiB; complete escaped Activity APNs payload: 4 KiB. State replaces the full JSON value. Notifications and updates share the daily push quota.
Errors are {ok:false,code,error?,details?,request_id?,timestamp?}. HTTP 400 indicates invalid arguments/schema/payload; 401 invalid or expired credentials; 403 denied scope or unavailable account access; 404 invisible resources; 409 stale revisions, conflicting idempotency or pending tokens; 410 revoked resources; 429 exhausted quota/rate limit. Inspect code: VERSION_CONFLICT needs a fresh read and business decision, IDEMPOTENCY_CONFLICT needs corrected request persistence, TOKEN_PENDING needs registration, and PUSH_LIMIT_EXCEEDED needs available daily quota. These are not reasons to loop with a new key.
Poll the operation after acceptance. An unknown start must be reconciled using the same launch; do not start another instance. Retries retain the same idempotency key and payload. A new business lifecycle deliberately uses a new generation.
