{"openapi":"3.1.0","info":{"title":"Page Change API","version":"1.0.0","description":"Prepaid monitoring of explicitly requested public pages for explicitly requested changes. A monitor buys a baseline plus a fixed number of scheduled checks; monitoring stops when checks are used up, the window ends, the condition is met (conditional types), or the customer cancels. Payment: x402 v2, USDC. Operated by Active Life Hub LLC.","contact":{"url":"https://pagechange.online/docs"},"termsOfService":"https://pagechange.online/terms"},"servers":[{"url":"https://pagechange.online"}],"x-payment":{"protocol":"x402","version":2,"scheme":"exact","asset":"USDC","network":"eip155:8453"},"components":{"securitySchemes":{"accessKey":{"type":"http","scheme":"bearer","description":"The Idempotency-Key used to create the monitor (24–128 chars of A-Z a-z 0-9 _ -). Stored only as a SHA-256 hash."}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{"type":"array"}}}}},"MonitorRequest":{"type":"object","additionalProperties":false,"required":["url","what_to_watch"],"properties":{"url":{"type":"string","format":"uri","description":"Public http(s) page on port 80/443. Private, local, metadata and IP-literal hosts are refused."},"what_to_watch":{"type":"string","maxLength":500,"description":"Free text in any language."},"change_type":{"type":"string","enum":["ANY_MEANINGFUL_CHANGE","TEXT_CHANGE","TEXT_APPEARS","TEXT_DISAPPEARS","SECTION_CHANGE","PRICE_CHANGE","PRICE_BELOW","PRICE_ABOVE","AVAILABILITY_CHANGE","BECOMES_AVAILABLE","BECOMES_UNAVAILABLE","STRUCTURED_FIELD_CHANGE","ITEM_ADDED","ITEM_REMOVED"],"default":"ANY_MEANINGFUL_CHANGE"},"threshold":{"type":"number","description":"Required for PRICE_BELOW / PRICE_ABOVE (page currency)."},"currency":{"type":"string","pattern":"^[A-Za-z]{3}$","description":"ISO 4217 code to pick among several prices."},"text":{"type":"string","maxLength":300,"description":"Required for TEXT_APPEARS / TEXT_DISAPPEARS. Case-insensitive, Unicode-normalized."},"selector":{"type":"string","maxLength":300,"description":"CSS selector to pin the watched region."},"field":{"type":"string","maxLength":200,"description":"STRUCTURED_FIELD_CHANGE: JSON-LD dotted path (e.g. offers.price) or, with selector, an attribute name."},"frequency":{"type":"string","enum":["6h","12h","1d","3d","7d"],"default":"1d"},"max_checks":{"type":"integer","minimum":1,"maximum":120,"default":14},"expires_in_days":{"type":"integer","minimum":1,"maximum":180,"description":"Default: enough for all funded checks + 1 day."},"stop_on_trigger":{"type":"boolean","description":"Default true for conditional types (PRICE_BELOW/ABOVE, BECOMES_*, TEXT_APPEARS/DISAPPEARS)."},"preferred_output_language":{"type":"string","description":"BCP 47. Explanations: en, ru, uk, es, fr, de, pt, it, ja, zh, ko; others fall back to en. Evidence is never translated."},"webhook_url":{"type":"string","format":"uri","description":"Optional public HTTPS endpoint. Signed with HMAC-SHA256 (PageChange-Signature: t=<unix>,v1=<hex of HMAC(secret, t + \".\" + body)>). At most 3 attempts."}}},"Monitor":{"type":"object","description":"Monitor status, checks, baseline, current state and schedule."},"Event":{"type":"object","properties":{"event_id":{"type":"string"},"monitor_id":{"type":"string"},"sequence":{"type":"integer"},"checked_at":{"type":"string","format":"date-time"},"source_url":{"type":"string"},"final_url":{"type":"string"},"change_type":{"type":"string","description":"The monitor change_type, or TARGET_MISSING / TARGET_RESTORED."},"condition_met":{"type":["boolean","null"]},"previous_state":{"type":"object"},"current_state":{"type":"object"},"normalized_diff":{"type":"object"},"evidence_before":{"type":"array","items":{"type":"string"},"description":"Original source text, never translated."},"evidence_after":{"type":"array","items":{"type":"string"}},"source_language":{"type":"object"},"output_language":{"type":"string"},"summary":{"type":"string"},"confidence":{"type":"string","enum":["high","medium","low"]},"remaining_checks":{"type":"integer"},"monitor_status":{"type":"string"},"webhook":{"type":["object","null"]}}}}},"paths":{"/api/v1/health":{"get":{"summary":"Configuration health (no database). ?ready=1 adds a cached database check.","parameters":[{"name":"ready","in":"query","schema":{"type":"string","enum":["1"]}}],"responses":{"200":{"description":"OK"},"503":{"description":"Not configured"}}}},"/api/v1/pricing":{"get":{"summary":"Pricing formula, measured-cost basis and examples.","responses":{"200":{"description":"Pricing"}}}},"/api/v1/quote":{"post":{"summary":"Price for a monitor request (validation only; no page fetch, no database).","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonitorRequest"}}}},"responses":{"200":{"description":"Quote and x402 payment requirements"},"400":{"description":"Invalid request (validation, unsafe URL, invalid selector).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or malformed Authorization: Bearer <access key>.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (also returned for a wrong access key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Not configured or temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/monitors":{"post":{"summary":"Create a monitor. Without PAYMENT-SIGNATURE: 402 with x402 requirements. With it: verify → baseline → settle → schedule.","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{24,128}$"},"description":"Random secret; becomes the monitor access key. Replays return the same monitor."},{"name":"PAYMENT-SIGNATURE","in":"header","required":false,"schema":{"type":"string"},"description":"Base64 x402 v2 payment payload."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonitorRequest"}}}},"responses":{"200":{"description":"Idempotent replay of an existing monitor."},"201":{"description":"Created: monitor with baseline.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Monitor"}}}},"400":{"description":"Invalid request (validation, unsafe URL, invalid selector).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or malformed Authorization: Bearer <access key>.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Payment required (x402). PAYMENT-REQUIRED header carries the requirements."},"404":{"description":"Not found (also returned for a wrong access key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Idempotency-Key or payment already used for a different request."},"422":{"description":"Baseline failed (page unavailable, target not found, JS-only page). Payment is not settled."},"429":{"description":"Rate limited.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Not configured or temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/monitors/{id}":{"get":{"summary":"Monitor status, checks, baseline and current state.","security":[{"accessKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Monitor"},"400":{"description":"Invalid request (validation, unsafe URL, invalid selector).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or malformed Authorization: Bearer <access key>.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (also returned for a wrong access key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Not configured or temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/monitors/{id}/events":{"get":{"summary":"Change events (oldest first). Up to 100 most recent are retained.","security":[{"accessKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"after","in":"query","schema":{"type":"integer","minimum":0}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"Events","content":{"application/json":{"schema":{"type":"object","properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/Event"}}}}}}},"400":{"description":"Invalid request (validation, unsafe URL, invalid selector).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or malformed Authorization: Bearer <access key>.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (also returned for a wrong access key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Not configured or temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/monitors/{id}/cancel":{"post":{"summary":"Stop monitoring. Remaining checks stay on the monitor.","security":[{"accessKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Monitor"},"400":{"description":"Invalid request (validation, unsafe URL, invalid selector).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or malformed Authorization: Bearer <access key>.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (also returned for a wrong access key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Not configured or temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/monitors/{id}/resume":{"post":{"summary":"Resume a cancelled, triggered, errored or unscheduled monitor using remaining checks (no charge).","security":[{"accessKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Monitor"},"400":{"description":"Invalid request (validation, unsafe URL, invalid selector).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or malformed Authorization: Bearer <access key>.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (also returned for a wrong access key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Not resumable"},"429":{"description":"Rate limited.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Not configured or temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/monitors/{id}/fund":{"post":{"summary":"Add funded checks (x402). Reactivates exhausted/expired monitors and extends the window as needed.","security":[{"accessKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"PAYMENT-SIGNATURE","in":"header","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["checks"],"properties":{"checks":{"type":"integer","minimum":1,"maximum":120},"extend_days":{"type":"integer","minimum":0}}}}}},"responses":{"200":{"description":"Funding applied"},"400":{"description":"Invalid request (validation, unsafe URL, invalid selector).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or malformed Authorization: Bearer <access key>.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Payment required (x402)"},"404":{"description":"Not found (also returned for a wrong access key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Not configured or temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}