{"openapi":"3.1.0","info":{"title":"Empress Behavioral Substrate — Tenant API","version":"1.0.0","description":"Granular behavioral observability as a service. Emit any valid xAPI statement to an immutable, tenant-isolated ledger; read it back, export it wholesale, and consume the computed layer (analytics, per-actor personalization, spaced-repetition belief state). Unknown verbs are logged, never refused — Empress validates structure, not vocabulary."},"servers":[{"url":"https://empress-api.jdnyzio.workers.dev"}],"security":[{"tenantKey":[]}],"components":{"securitySchemes":{"tenantKey":{"type":"http","scheme":"bearer","description":"Your tenant API key (emp_<slug>_…)"}},"schemas":{"Statement":{"type":"object","required":["actor","verb","object"],"properties":{"actor":{"type":"object","description":"xAPI Agent; account.name carries your platform identity"},"verb":{"type":"object","required":["id"],"properties":{"id":{"type":"string","format":"uri"},"display":{"type":"object"}}},"object":{"type":"object","required":["id"],"description":"Activity; id convention https://empress.eco/objects/<publicId>"},"result":{"type":"object"},"context":{"type":"object"},"timestamp":{"type":"string","format":"date-time"}}},"RerankRequest":{"type":"object","required":["actorId","candidates"],"properties":{"actorId":{"type":"string"},"candidates":{"type":"array","maxItems":500,"items":{"type":"object","required":["id"],"properties":{"id":{"type":"string"},"publicId":{"type":"string"},"templateType":{"type":"string","nullable":true},"creator":{"type":"string","nullable":true},"tags":{"type":"array","items":{"type":"string"}}}}}}},"RerankResult":{"type":"object","properties":{"signal":{"type":"boolean","description":"false = no meaningful history; use your default order"},"order":{"type":"array","items":{"type":"string"}},"scores":{"type":"object","additionalProperties":{"type":"number"}}}}}},"paths":{"/statements":{"post":{"summary":"Emit a statement (immutable ledger; quota-enforced per tier)","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Statement"}}}},"responses":{"200":{"description":"Stored"},"400":{"description":"xAPI validation failed"},"429":{"description":"Tenant quota exceeded"}}},"get":{"summary":"Read your tenant's recent statements (tenant-isolated)","parameters":[{"name":"agent","in":"query","schema":{"type":"string"},"description":"Plain actor id (convenience) or spec IFI JSON"},{"name":"activity","in":"query","schema":{"type":"string","format":"uri"}},{"name":"verb","in":"query","schema":{"type":"string","format":"uri"}},{"name":"since","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"until","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"limit","in":"query","schema":{"type":"integer","maximum":2000}}],"responses":{"200":{"description":"Your statements only — isolation enforced substrate-side"}}}},"/export":{"get":{"summary":"Export your entire ledger (NDJSON, cursor-paged; your data is portable by construction)","parameters":[{"name":"since","in":"query","schema":{"type":"string","format":"date-time"},"description":"Cursor from the previous page's X-Next-Since header"},{"name":"limit","in":"query","schema":{"type":"integer","maximum":1000}}],"responses":{"200":{"description":"application/x-ndjson lines {stored, statement}; X-Next-Since + X-Count headers"}}}},"/analytics/trending":{"post":{"summary":"Population play-counts over a window (test traffic excluded)","responses":{"200":{"description":"{ counts: { [objectId]: number } }"}}}},"/analytics/rerank":{"post":{"summary":"Per-actor personalized ordering over your candidates","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RerankRequest"}}}},"responses":{"200":{"description":"Personalized order","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RerankResult"}}}}}}},"/analytics/actor/{actorId}/stats":{"get":{"summary":"An actor's aggregate stats (sessions, scores, skill profile)","parameters":[{"name":"actorId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Actor stats"}}}},"/analytics/difficulty/{objectId}":{"get":{"summary":"Population-derived difficulty for an object","parameters":[{"name":"objectId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Difficulty"}}}},"/analytics/summary":{"get":{"summary":"Tenant activity summary","responses":{"200":{"description":"Summary"}}}},"/belief/{actorId}":{"get":{"summary":"Full FSRS belief map for an actor (spaced-repetition state per concept)","parameters":[{"name":"actorId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Belief state"}}}},"/belief/{actorId}/recommended":{"get":{"summary":"What this actor should engage next (due reviews / ready-to-learn / at-boundary)","parameters":[{"name":"actorId","in":"path","required":true,"schema":{"type":"string"}},{"name":"strategy","in":"query","schema":{"type":"string","enum":["review","learn","challenge"]}}],"responses":{"200":{"description":"Recommendations"}}}}}}