Skip to main content

API-eksempler

Bruk denne siden til å kopiere riktig forespørselsform for hver utvidelsesflyt.

  • Eksempler på iframe-broer bruker postMessage-handlinger som session.get, state.get og files.get.
  • Privilegerte eksempler bruker din egen utvidelsesbackend med Authorization: Bearer YOUR_APP_SCOPED_DEVELOPER_KEY og x-chastify-main-token.
  • Send aldri en Developer API-nøkkel til iframe eller nettleserkode.
info

Iframe-broen er for UI-oppstart og lavrisiko-øktoperasjoner. Bruk den til å lese kontekst, lagre utvidelseseid tilstand og løse fil-URL-er.

caution

Nettleserens iframe-kode er brukerstyrt. Ikke bruk iframe-broforespørsler til å bruke/fjerne tid, fullføre oppgaver, fjerne opplåsingsblokkeringer, laste opp/slette kjøretidsfiler, sende varsler, skrive logger eller kommandere enheter.

Forespørsels- og svarformat

Sikre iframe-brohandlinger sendes i denne broforespørselskonvolutten:

{
"type": "chastify:ext:req", // required
"v": 1, // protocol version
"id": "req-123", // your unique request id
"nonce": "from-iframe-hash",
"action": "session.get",
"payload": {}
}

Og du mottar:

{
"type": "chastify:ext:resp",
"v": 1,
"id": "req-123", // same id you sent
"ok": true,
"data": {}
}

Hvis ok er false, kryss av for error.code og error.message.

Eksempler som kun brukes i backend-format bruker vanlige HTTPS-forespørsler fra serveren din. De sendes ikke via iframe-broen.

Økt og kontekst

session.get

Bruk dette først i nesten alle utvidelsesflyter.

Hva den gjør:

  • Bekrefter at broforbindelsen din fungerer.
  • Returnerer øktkontekst (låsestatus, rolle, utvidelseskonfigurasjon, funksjoner).
  • Returnerer informasjon om enhetsfunksjonalitet som brukergrensesnittet ditt kan bruke før det ber backend-enheten om å kalle device.command.

Hva det brukes til:

  • Bootstrapping av brukergrensesnittet ditt.
  • Aktivering/deaktivering av funksjoner basert på rolle og tillatelser.
  • Kontrollerer støttede enhetskommandoer før gjengivelse av enhetskontroller.

Eksempel på handlingsnyttelast:

{
"action": "session.get",
"payload": {}
}

Eksempel på session.get-svarutdrag (låsedata for kjøretid):

{
"ok": true,
"data": {
"lockData": {
"frozen": false,
"unlockable": false,
"trusted": true,
"taskAssigned": true,
"timeLockedSeconds": 1420,
"timeRemainingSeconds": 27800,
"maxTimeRemainingSeconds": 86400,
"taskPoints": 12,
"taskPointsRequired": 20,
"lockTitle": "Weekend Challenge",
"wearerUsername": "alice",
"keyholderUsername": "kh_bob",
"wearerLastSeenTimestamp": 1739640505123,
"keyholderLastSeenTimestamp": null
}
}
}

Personvernmerknader:

  • wearerLastSeenTimestamp / keyholderLastSeenTimestamp returneres bare hvis brukeren har showOnlineStatus !== false.
  • Hvis synlighet av onlinestatus er deaktivert, er disse feltene null.

Flyter for backend-utvidelser

Disse eksemplene viser det sikre produksjonsmønsteret:

  1. Iframe-en leser mainToken og sessionId fra hash-nyttelasten.
  2. Iframe-en sender dem til backend-en din.
  3. Backend-en din validerer din egen spill-/oppgave-/forretningstilstand.
  4. Backend-en din kaller Chastify med en app-scoped Developer API-nøkkel pluss x-chastify-main-token.

Ikke bruk sessionId alene som autentisering. Behandle mainToken som en oppstartskontekst som er synlig i nettleseren, og behandle Developer API-nøkkelen din som en hemmelighet kun for backend.

warning

Backend-en din må validere sin egen spill-/oppgavestatus før den kaller Chastify. Å sende mainToken og sessionId fra iframe-en identifiserer bare den åpnede utvidelsesøkten; det beviser ikke at brukeren fullførte en utfordring.

Hent øktkontekst på en sikker måte

Iframen din kan bruke den sikre broen session.get for UI-oppstart. Hvis backend-en din trenger samme kontekst før en privilegert handling kan brukes, må du hente den fra backend-en din med begge påloggingsinformasjonene.

Iframe:

const hash = JSON.parse(decodeURIComponent(window.location.hash.slice(1)));

await fetch("/api/my-extension/session-context", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
mainToken: hash.mainToken,
sessionId: hash.sessionId
})
});

Bakenden din:

app.post("/api/my-extension/session-context", async (req, res) => {
const { mainToken, sessionId } = req.body;

const response = await fetch(
`https://chastify.net/api/extensions/sessions/${encodeURIComponent(sessionId)}`,
{
headers: {
Authorization: `Bearer ${process.env.CHASTIFY_APP_DEVELOPER_KEY}`,
"x-chastify-main-token": mainToken
}
}
);

if (!response.ok) {
return res.status(response.status).json(await response.json());
}

const context = await response.json();

res.json({
role: context.role,
config: context.extensionConfig,
lockData: context.lockData
});
});

Bruk tid fra en utvidelsesbackend

Nettleseren kan be backend-serveren din om å bruke en belønning eller straff, men nettleseren må ikke avgjøre om handlingen er gyldig. Bekreft handlingen på serversiden først.

app.post("/api/my-extension/apply-reward", async (req, res) => {
const { mainToken, sessionId, runId } = req.body;

const run = await db.gameRuns.findUnique({ where: { id: runId } });
if (!run || run.sessionId !== sessionId || !run.serverVerifiedWin) {
return res.status(403).json({ error: "game_not_verified" });
}

const response = await fetch(
`https://chastify.net/api/extensions/sessions/${encodeURIComponent(sessionId)}/action`,
{
method: "POST",
headers: {
"content-type": "application/json",
Authorization: `Bearer ${process.env.CHASTIFY_APP_DEVELOPER_KEY}`,
"x-chastify-main-token": mainToken
},
body: JSON.stringify({
name: "remove_time",
params: 300
})
}
);

if (!response.ok) {
return res.status(response.status).json(await response.json());
}

res.json(await response.json());
});

Bruk add_time for straffer og remove_time for belønninger.

Serververifisert spillfullføring

For spill som Simon Says, ikke stol på en klientrapportert gevinst. Opprett kjøringen på serversiden, lagre den forventede sekvensen eller en hash av den, og bekreft den innsendte inputen før du kaller Chastify.

Et nettlesersynlig minnespill kan ikke bevise at et menneske har spilt ærlig, fordi nettleseren må motta sekvensen for å gjengi spillet. Serververifisering forhindrer fortsatt forfalskede Chastify-mutasjoner og lar backend-en din håndheve løps-ID-er, utløp, vanskelighetsgrad, kadens, poengsum og replay-beskyttelse før belønninger eller straffer iverksettes.

app.post("/api/simon/runs", async (req, res) => {
const { mainToken, sessionId } = req.body;
await verifySessionLaunch({ mainToken, sessionId });

const sequence = createSimonSequence();

const run = await db.simonRuns.create({
data: {
sessionId,
sequenceHash: hashSequence(sequence),
expiresAt: new Date(Date.now() + 5 * 60_000)
}
});

res.json({
runId: run.id,
sequence
});
});

app.post("/api/simon/runs/:runId/complete", async (req, res) => {
const { mainToken, sessionId, input } = req.body;
await verifySessionLaunch({ mainToken, sessionId });

const run = await db.simonRuns.findUnique({ where: { id: req.params.runId } });

if (!run || run.sessionId !== sessionId || run.expiresAt < new Date()) {
return res.status(403).json({ error: "run_invalid" });
}

const won = hashSequence(input) === run.sequenceHash;
await db.simonRuns.update({
where: { id: run.id },
data: { completedAt: new Date(), serverVerifiedWin: won }
});

if (won) {
await fetch(`https://chastify.net/api/extensions/sessions/${encodeURIComponent(sessionId)}/requirements/progress`, {
method: "POST",
headers: {
"content-type": "application/json",
Authorization: `Bearer ${process.env.CHASTIFY_APP_DEVELOPER_KEY}`,
"x-chastify-main-token": mainToken
},
body: JSON.stringify({
key: "simon_says_wins",
amount: 1
})
});
}

res.json({ won });
});

Det nøyaktige lagringsskjemaet for kjører er ditt. verifySessionLaunch bør kalle Chastify med din app-scoped Developer API-nøkkel og x-chastify-main-token før sessionId stoles på. Den viktige regelen er at Chastify-mutasjoner bare skjer etter at backend-en din har bekreftet oppstarten og resultatet.

Planlagte krav

Backend-systemet ditt eier tidsplaner, kadenskontroller og bevisvalidering. Bruk Chastify kun til å registrere pålitelig fremdrift eller oppdatere opplåsingsblokkeringer etter at backend-systemet ditt har bestemt at kravet er oppfylt.

async function recordDailyRequirementProgress({ sessionId, mainToken, userId }) {
const completed = await db.dailyCheckins.exists({
where: {
userId,
day: new Date().toISOString().slice(0, 10),
verified: true
}
});

if (!completed) return;

await fetch(`https://chastify.net/api/extensions/sessions/${encodeURIComponent(sessionId)}/requirements/progress`, {
method: "POST",
headers: {
"content-type": "application/json",
Authorization: `Bearer ${process.env.CHASTIFY_APP_DEVELOPER_KEY}`,
"x-chastify-main-token": mainToken
},
body: JSON.stringify({
key: "daily_checkin",
amount: 1
})
});
}

Nåværende API-er for installerte utvidelsesøkter krever et gyldig iframe-oppstartstoken i x-chastify-main-token. Oppstartstokener utløper for øyeblikket etter 10 timer. For planlagte jobber som kjører etter at tokenet utløper, lagrer du ditt eget ventende bevis og sender inn fremdriften ved neste gyldige utvidelsesoppstart, eller bruker en førsteparts-/innebygd serverflyt designet for uovervåket bakgrunnsarbeid.

caution

Ikke behandle planlagte jobber som klarerte bare fordi de kjører på serveren din. Jobben trenger fortsatt bevis på serversiden, kadenskontroller, avspillingsbeskyttelse og en gyldig Chastify-autorisasjonssti før kravfremdriften registreres.

Varsler

notifications.custom

Bruk dette fra utvidelsens backend for å sende et tilpasset utvidelsesvarsel til bruker, nøkkelinnehaver eller begge deler.

Endepunkt:

POST /api/extensions/sessions/:sessionId/notifications/custom
Authorization: Bearer YOUR_APP_SCOPED_DEVELOPER_KEY
x-chastify-main-token: MAIN_TOKEN_FROM_IFRAME_HASH

Eksempel på brødtekst:

{
"title": "Extension Reminder",
"message": "Your next challenge is ready.",
"showPageOverlay": false,
"target": "both"
}

Merknader:

  • showPageOverlay har standardverdien false.
  • target har standardverdien wearer.
  • API-et oppretter varslingstypen extension_app_message.

Utvidelsesstatus

Utvidelsesstatus er dine utvidelseseide JSON-data for den gjeldende låseøkten. Tilstandsskrivinger er kun for backend og krever en app-scoped Developer API-nøkkel pluss økten mainToken. Iframes kan lese tilstand med state.get, men de kan ikke skrive tilstand direkte.

state.put

Hva den gjør:

  • Erstatter hele tilstandsobjektet med det nye data-objektet.
  • Krever backend-legitimasjon.

Når du skal bruke:

  • Første lagring.
  • Full overskriving når du allerede har den komplette nye tilstanden.

Eksempel:

curl -X PUT "https://chastify.net/api/extensions/sessions/$SESSION_ID/state" \
-H "Authorization: Bearer $DEVELOPER_KEY" \
-H "x-chastify-main-token: $MAIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"data": {
"counter": 1,
"notes": "first test"
}
}'

Feltnotater:

  • payload.data: en hvilken som helst gyldig JSON-verdi/-objekt som utvidelsen din trenger.
  • Avoid Mongo-unsafe key names ($ prefix or keys containing .).
  • Tilstanden er øktbegrenset og størrelsesbegrenset av utvidelsesappens stateMaxBytes, med standardinnstilling på 64 KiB.
  • Lagre fil-ID-er i tilstand, ikke binære filer eller signerte URL-er. Bruk files.get for å oppdatere signerte URL-er før gjengivelse av media.

state.patch

Hva den gjør:

  • Bruker en JSON-flettingsoppdatering på eksisterende tilstand.
  • Bare endrede nøkler må sendes.
  • Krever backend-legitimasjon.

Når du skal bruke:

  • Trinnvise oppdateringer fra brukerinteraksjoner.
  • Oppdaterer ett felt uten å sende alt på nytt.

Eksempel:

curl -X PATCH "https://chastify.net/api/extensions/sessions/$SESSION_ID/state" \
-H "Authorization: Bearer $DEVELOPER_KEY" \
-H "x-chastify-main-token: $MAIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"data": {
"counter": 2
}
}'

state.get

Hva den gjør:

  • Leser gjeldende status for utvidelsen.
  • Tilgjengelig via iframe-broen.

Når du skal bruke:

  • Ved innlasting av iframe.
  • Etter skrivinger, hvis du vil synkronisere det lokale brukergrensesnittet på nytt.

Eksempel:

{
"action": "state.get",
"payload": {}
}

Fillagring

Bruk files.* for binære medier som puslespillbilder, genererte forhåndsvisninger eller utfordringsbilder. Lagre den returnerte file.id i backend-skrevet tilstand eller i din egen database. Gjengi med file.signedUrl, og oppdater den signerte URL-en med files.get når iframe-en lastes inn senere.

Oppsettskjermer som kjører før en lås/økt eksisterer, bruker trinnvise opplastinger i stedet for files.upload. Trinnvise filer er midlertidige inntil utvidelseskonfigurasjonen lagres med en provider: "chastify_storage"- og fileId-referanse. Chastify krever disse filene automatisk ved låsing/mallagring; det er ikke noe separat kravkall på nettlesersiden.

Eksempel på delt tilstand/fil fra backend-systemet ditt:

curl -X PATCH "https://chastify.net/api/extensions/sessions/$SESSION_ID/state" \
-H "Authorization: Bearer $DEVELOPER_KEY" \
-H "x-chastify-main-token: $MAIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"data": {
"puzzleImageFileId": "file_record_id"
}
}'

Senere, løs opp bildet før visning:

const state = await bridge.request("state.get", {});
const file = await bridge.request("files.get", {
fileId: state.data.puzzleImageFileId
});
image.src = file.file.signedUrl;

files.capabilities

Sjekk dette før du viser opplastingskontroller.

{
"action": "files.capabilities",
"payload": {}
}

Kjøretid files.upload

Opplasting av kjøretidsfiler muterer utvidelsesøktsdata, så det er ikke en iframe-brokommando. Last opp kjøretidsfiler fra backend-en din med en app-scoped Developer API-nøkkel og x-chastify-main-token.

files.get

Oppdater én signert R2-URL fra en stabil fil-ID.

{
"action": "files.get",
"payload": {
"fileId": "file_record_id"
}
}

files.list

{
"action": "files.list",
"payload": {}
}

Kjøretidsprogrammet files.delete er også kun for backend av samme grunn som opplasting.

Låshandlinger

Legg til tid

Endepunkt: POST /api/extensions/sessions/:sessionId/action

Hva den gjør:

  • Legger til eller fjerner tid fra nedtellingen til låsen, avhengig av deltaSeconds.

Når du skal bruke:

  • Belønnings-/straffeknapper.
  • Kamputfall (seier legger til tid, tap fjerner tid).

Eksempel:

{
"name": "add_time",
"params": 300 // +300 sec = +5 minutes
}

Feltnotater:

  • Positiv verdi tilfører tid.
  • Negativ verdi fjerner tid (hvis tillatt av serverreglene).

Fryse

Endepunkt: POST /api/extensions/sessions/:sessionId/action

Hva den gjør:

  • Fryser låseprogresjonen i en viss periode.

Når du skal bruke:

  • Nedkjølingsmekanikk.
  • Belønningssjekkpunkter.

Eksempel:

{
"name": "freeze",
"params": { "durationSeconds": 120 }
}

Du kan også kalle det uten durationSeconds:

{
"name": "freeze",
"params": {}
}

Feltnotater:

  • durationSeconds er valgfritt.
  • Hvis utelatt, er gjeldende standard 3600 sekunder (1 time).
  • Akseptert område er 60 til 86400 sekunder.

Tin opp

Endepunkt: POST /api/extensions/sessions/:sessionId/action

Hva den gjør:

  • Avslutter aktiv frysing og gjenopptar normal timeroppførsel.

Når du skal bruke:

  • Manuell overstyring i arbeidsflyter for utvidelser.
  • «Avbryt frysing»-kontroller.

Eksempel:

{
"name": "unfreeze",
"params": {}
}

Gapestokk

Endepunkt: POST /api/extensions/sessions/:sessionId/action

Hva den gjør:

  • Starter en gapestokkperiode for den aktive låseøkten.

Når du skal bruke:

  • Straffemekanismer etter mislykkede oppgaver/utfordringer.
  • Eskaleringsflyter som midlertidig begrenser låsesamhandling.

Eksempel:

{
"name": "pillory",
"params": {
"durationSeconds": 600,
"reason": "Missed scheduled check-in"
}
}

Feltnotater:

  • name må være pillory.
  • params.durationSeconds er obligatorisk.
  • params.reason er valgfritt.
  • Krever at gapestokken er aktivert i øktkonfigurasjonen.

Endegapestokk

Endepunkt: POST /api/extensions/sessions/:sessionId/action

Hva den gjør:

  • Avslutter den gjeldende aktive gapestokkøkten umiddelbart.

Eksempel:

{
"name": "pillory.end",
"params": {}
}

Feltnotater:

  • name må være pillory.end.
  • Mislykkes med pillory_not_active hvis låsen ikke er i gapestokken for øyeblikket.

Tildel oppgave

Endepunkt: POST /api/extensions/sessions/:sessionId/action

Hva den gjør:

  • Oppretter en aktiv oppgavekjøring for brukeren fra utvidelseslogikk.
  • Kan overstyre en allerede åpen oppgavekjøring.

Eksempel:

{
"name": "task.assign",
"params": {
"taskText": "Clean your room",
"points": 10,
"verificationRequired": true,
"durationSeconds": 1800
}
}

Feltnotater:

  • taskText er obligatorisk.
  • points er valgfri og begrenset på serversiden.
  • verificationRequired har standardverdien false.
  • durationSeconds er valgfritt (0 betyr at det ikke er behov for timer).
  • Krever at Oppgaver-modulen er aktivert på låsen.

Start oppgavetimeren

Endepunkt: POST /api/extensions/sessions/:sessionId/action

Hva den gjør:

  • Starter eller starter nedtellingsvinduet på nytt for den aktive tidsbestemte oppgaven.

Eksempel:

{
"name": "task.start_timer",
"params": {}
}

Feltnotater:

  • Krever en aktiv oppgavekjøring.
  • Mislykkes hvis den gjeldende oppgaven ikke har konfigurert varighet.

Fullfør oppgaven

Endepunkt: POST /api/extensions/sessions/:sessionId/action

Hva den gjør:

  • Markerer den aktive oppgaven som fullført eller mislykket.

Eksempel (suksess):

{
"name": "task.complete",
"params": {
"successful": true
}
}

Eksempel (feil):

{
"name": "task.complete",
"params": {
"successful": false,
"reason": "Did not finish in time"
}
}

Utløs midlertidig åpning

Endepunkt: POST /api/extensions/sessions/:sessionId/action

Hva den gjør:

  • Starter et midlertidig åpningsvindu for hygiene fra utvidelseslogikk.

Eksempel:

{
"name": "hygienic_unlock.start",
"params": {
"durationSeconds": 900
}
}

Feltnotater:

  • Krever at hygienisk åpning er aktivert på låsen.
  • Mislykkes hvis en hygieneåpning allerede pågår.
  • durationSeconds er valgfritt; standardlås brukes når det utelates.

Metadata og startsidehandlinger

metadata.patch

Hva den gjør:

  • Lagrer utvidelsesmetadata som brukes av brukergrensesnittet for låste sider.
  • Støtter unlockBlockers og homeActions.
  • Støtter homeActions[].intent for dyplenke-atferd når utvidelsen åpnes.

Når du skal bruke:

  • Håndhev opplåsingsbetingelser for låseøkter som eies av utvidelsen din.
  • Legg til hurtighandlinger på låsesiden som åpner utvidelsen din med vilje.
  • Send brukere direkte til en bestemt skjerm/arbeidsflyt når de klikker på en startsidehandling.

Endepunkt:

PATCH /api/extensions/sessions/:sessionId/metadata
Authorization: Bearer YOUR_APP_SCOPED_DEVELOPER_KEY
x-chastify-main-token: MAIN_TOKEN_FROM_IFRAME_HASH

Eksempel på brødtekst:

{
"unlockBlockers": ["Finish extension task"],
"homeActions": [
{
"slug": "tasks",
"title": "Tasks",
"description": "Open tasks panel",
"intent": {
"type": "open_panel",
"title": "Tasks",
"message": "Open tasks panel",
"payload": {
"panel": "regular-actions"
}
}
}
]
}

Feltnotater:

  • unlockBlockers: liste over aktive blokkeringer for opplåsing av låseøkter fra utvidelsen din.
  • Du kan inkludere flere blokkeringer samtidig (opptil 25), én per udekket betingelse.
  • Opplåsing forblir blokkert så lenge det finnes en blokkering på tvers av aktiverte utvidelser.
  • Chastify samler blokkeringer fra alle utvidelser for låseøkten.
  • Utvidelsen din skal bare legge til/fjerne sine egne blokkeringer i sine egne metadata.
  • Ikke fjern blokkeringer fra andre utvidelser; fjern bare arrayet ditt når dine egne betingelser er oppfylt.
  • homeActions: hurtigknapper vises i låseopplevelsen.
  • homeActions[].slug: stabil ID for handlingen din.
  • homeActions[].title: brukerrettet etikett.
  • homeActions[].description: valgfri hjelpetekst.
  • homeActions[].intent: valgfri dyplenkeinstruksjon sendt til utvidelsen din når den åpnes.
  • I brukergrensesnittet på utvidelseskortet vises disse handlingene som en meny/liste etter handlingstittel (internt tastet inn av slug).
  • Når en bruker klikker på en, åpner Chastify utvidelsen og sender:
    • homeActionSlug
    • homeAction (valgt handlingsobjekt)
    • intent (normalisert intensjonsobjekt) slik at utvidelsen din umiddelbart kan rute til riktig visning/handling ved innlasting.

Intents: eksempel på utviklerapp

Bruk dette mønsteret i utvidelsesappen din for å reagere på menyklikk-intensjoner ved lasting.

import { useEffect, useRef } from "react";
import { parseHashPayload, type IframeHashPayload } from "../lib/ChastifyBridge";

export function useHomeActionIntent(
payload: IframeHashPayload,
routeToPanel: (panel: string) => void,
showToast: (message: string) => void,
) {
const handledRef = useRef<string>("");

useEffect(() => {
const homeActionSlug = payload?.homeActionSlug ?? null;
if (!homeActionSlug) return;

// Prevent duplicate handling if component re-renders.
const key = `${payload.lockId || "lock"}:${homeActionSlug}`;
if (handledRef.current === key) return;
handledRef.current = key;

const intent = payload?.intent ?? payload?.homeAction?.intent ?? null;
if (!intent) return;

if (intent.type === "open_panel") {
const panel = String(intent.payload?.panel || "");
if (panel) routeToPanel(panel);
return;
}

if (intent.message) {
showToast(String(intent.message));
}
}, [payload, routeToPanel, showToast]);
}

// Example app bootstrap
const payload = parseHashPayload();
if (!payload) throw new Error("Missing iframe hash payload");

Hva dette eksemplet gjør:

  • Leser homeActionSlug + intent fra iframe-hash-nyttelasten.
  • Håndterer hvert klikk bare én gang per lås-/handlingsslug.
  • Ruter til et panel når intensjonen er open_panel.
  • Går tilbake til å vise en intensjonsmelding for tilpassede intensjonstyper.

Enhetskommando

device.command

Hva den gjør:

  • Sender en enhetskontrollkommando (hvis støttes for den økten/enheten).
  • Lar forlengelsesenheten utløse standardiserte støt-/vibrasjonshandlinger gjennom Chastify.

Når du skal bruke:

  • Utløser støttede støt-/vibrasjonskommandoer fra utvidelseslogikk.
  • Bygge interaktive utvidelsesfunksjoner (spill, straffer, belønninger, rutiner).

Endepunkt:

POST /api/extensions/sessions/:sessionId/device-command
Authorization: Bearer YOUR_APP_SCOPED_DEVELOPER_KEY
x-chastify-main-token: MAIN_TOKEN_FROM_IFRAME_HASH

Eksempel på brødtekst:

{
"command": "shock.start",
"params": {
"durationSeconds": 30,
"intensityPct": 50
}
}

Vanlige kommandoer:

  • shock.start med parameterne: { durationSeconds, intensityPct, message? }
  • shock.stop
  • vibration.start med parameterne: { durationSeconds, intensityPct, frequencyPct?, message? }
  • vibration.stop
  • all.stop
  • shock.random.set med parameterne: { enabled, minIntensityPct?, maxIntensityPct?, message? } (kun Lockink AA-A1012)
  • shock.berserk.set med parameterne: { enabled, message? } (kun Lockink AA-A1012)

Anbefalt strømning:

  1. Kall session.get ved lasting.
  2. Les enhetsfunksjoner fra deviceControl.supportedCommands.
  3. Gjengi kun kontroller for støttede kommandoer.
  4. Send device.command med validerte verdier.
  5. Oppdater eller stol på svaret active-flagg for status for live UI.

Parameterveiledning:

  • durationSeconds: serveren holder seg innenfor sikre grenser (gjeldende maks. for regelen er 300 sekunder).
  • intensityPct: forventet prosentverdi (1-100-stilinndata, begrenset på serversiden).
  • frequencyPct: forventet prosentverdi (1-100) for vibrasjonsflyter (fastklemt på serversiden).
  • For tilfeldig modus, sørg for minIntensityPct <= maxIntensityPct.

Eksempel på et sikrere brukergrensesnittmønster:

// 1) Get capabilities first
const session = await bridge.request("session.get", {});
const supported = new Set(session?.deviceControl?.supportedCommands ?? []);

// 2) Only call command if supported
if (supported.has("shock.start")) {
await bridge.request("device.command", {
command: "shock.start",
params: { durationSeconds: 30, intensityPct: 50 }
});
}

Viktig:

  • Kall session.get først og les støttede kommandoer.
  • Vis bare kontroller for kommandoer som støttes i gjeldende økt.
  • Valider brukerinndata før du sender kommandoparametere.
  • device.command krever skrivetillatelse (locks:write) for utvidelsesøkten.
  • Håndter bro-/serverfeil på en elegant måte (insufficient_scope, kommando som ikke støttes, valideringsfeil).

Krav til utvidelse

Utvidelseskrav lar en utvidelse definere regelmessige fullføringsregler som vises i låsens brukergrensesnitt for fremdrift i dag, og kan ilegge en straff når brukeren går glipp av et vindu.

Bruk dette for serverklarerte utvidelsesaktiviteter som:

  • Fullfør 1 puslespill per dag.
  • Fullfør 3 innsjekkinger annenhver dag.
  • Fullfør 5 utvidelseshandlinger per uke.

Konfigurasjonsform

Kravet er lagret i konfigurasjonen for utvidelsesøkten under extensionRequirements:

{
"extensionRequirements": {
"enabled": true,
"metric": "completion",
"requiredCount": 1,
"cadence": {
"every": 1,
"unit": "day"
},
"punishment": {
"type": "add_time",
"seconds": 900,
"reason": "Missed extension requirement"
}
}
}

Felt:

  • enabled: slår det gjentakende kravet av/på.
  • metric: Stabilt tellernavn. Bruk enkle navn som completion, win eller verification.
  • requiredCount: hvor mange klarerte hendelser som må skje i vinduet.
  • cadence.every: intervallstørrelse.
  • cadence.unit: day eller week.
  • Vindustidssonen løses av Chastify fra brukerens konfigurerte User.timezone. Utvidelseskonfigurasjonen skal ikke hardkode en tidssone.
  • punishment.type: none, add_time, freeze eller pillory.
  • punishment.seconds: straffevarighet for add_time, freeze eller pillory.
  • punishment.reason: valgfri revisjons-/feilsøkingsårsak.

Fremdriftsmodell

Kravfremdriften er klarert serversidetilstand, ikke iframe-lokal tilstand.

Ikke bruk state.patch / state.put for å markere et krav som fullført. Disse handlingene er generelle tilstandsskrivinger kun for backend, ikke API-er for kravfremdrift. Kravfremdrift må bare registreres etter at serveren validerer hendelsen som skal telle.

For eksempel:

  • En puslespillutvidelse skal bare registrere fremgang etter at serveren validerer den signerte puslespillkjøringen og fullført tilstand.
  • En bekreftelsesutvidelse skal bare registrere fremdrift etter at serveren har godtatt det innsendte beviset.
  • En spillutvidelse skal bare registrere fremgang etter at backend-systemet validerer spillresultatet eller den pålitelige fullføringshendelsen.

Kjøretidsoppførsel

Når konfigurert:

  • Låsedashbordet kan vise kravet i Dagens fremdrift.
  • Chastify sporer fremgang per forlengelsesøkt og per kadensvindu.
  • Den planlagte kravjobben evaluerer fullførte vinduer og bruker den konfigurerte straffen én gang per tapt vindu.
  • Straffer er idempotente per vindu, så nye forsøk stabler ikke dupliserte straffer.
  1. Konfigurer extensionRequirements i brukergrensesnittet for oppsett/konfigurasjon av utvidelsen.
  2. Ved oppstart under kjøring, kall session.get og les den aktive konfigurasjonen.
  3. Fullfør utvidelsesaktiviteten i brukergrensesnittet.
  4. Send fullføringen til en klarert backend-rute for den utvidelsen.
  5. La backend-systemet validere fremdriften for hendelsen og registreringskravet.
  6. Oppdater det lokale brukergrensesnittet med session.get / state.get etter at det er fullført.

Viktig:

  • Behandle state.* kun som utvidelseseid lagring. Bruk dedikerte, pålitelige API-er for fremgang, forsøk, belønninger og straffer.
  • Ikke stol på klientens fullføringsflagg for krav.
  • Hold metric-navnene stabile; endring av metrikken begynner å telle i en annen kategori.
  • Chastify bruker brukerens konfigurerte tidssone for kadensvinduer. Hvis ingen tidssone er tilgjengelig for brukeren, går serveren tilbake til UTC.
  • Hold straffer begrenset og forklarlige i revisjonslogger.
  1. Kall session.get ved oppstart.
  2. Lesestatus med state.get.
  3. Utfør tilstandsskrivinger fra backend-en din med PUT/PATCH /state når det er nødvendig.
  4. Kjør lås-/enhetshandlinger bare når det støttes og er synlig i brukergrensesnittet.
  5. For kravbaserte aktiviteter, rapporter fullføring til en pålitelig backend-rute.
  6. Oppdater den lokale visningen etter viktige skrivinger/handlinger.