{"openapi":"3.1.0","info":{"title":"Prodantix API","version":"0.1.0"},"servers":[{"url":"https://api.prodantix.com","description":"Flags and messaging"},{"url":"https://eu.api.prodantix.com","description":"Event ingestion (EU)"},{"url":"https://eu.replay.prodantix.com","description":"Session replay (EU)"}],"paths":{"/v1/events":{"post":{"summary":"Ingest a batch of events","tags":["events"],"description":"Accepts a batch of analytics events. A 202 means accepted for processing, not persisted.","security":[{"projectKey":[]}],"servers":[{"url":"https://eu.api.prodantix.com"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"api_key":{"type":["string","null"]},"events":{"type":"array","items":{"$ref":"#/components/schemas/EventEnvelope"}},"sent_at":{"type":"string"}},"required":["events","sent_at"],"description":"Ports `EventBatch` (`.strict()`): an optional public api_key, 1–1000\nevents, and an ISO-8601 `sent_at`."}}}},"responses":{"202":{"description":"Accepted for processing","content":{"application/json":{"schema":{"type":"object","properties":{"accepted":{"type":"integer","format":"uint","minimum":0}},"required":["accepted"],"description":"`accepted` is `usize` to match what the handler already counted and\nserialized; narrowing it here would risk a panic on conversion for a wire\nvalue that has always been a plain JSON number."}}}},"400":{"description":"Malformed JSON or invalid payload","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer","format":"uint16","minimum":0,"maximum":65535},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message","error"]}}}},"401":{"description":"Missing or invalid project key","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer","format":"uint16","minimum":0,"maximum":65535},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message","error"]}}}},"403":{"description":"Project key belongs to a different region","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer","format":"uint16","minimum":0,"maximum":65535},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message","error"]}}}}}}},"/v1/identify":{"post":{"summary":"Identify a user","tags":["events"],"description":"Associates traits with a distinct id. A 202 means accepted for processing, not persisted.","security":[{"projectKey":[]}],"servers":[{"url":"https://eu.api.prodantix.com"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"distinct_id":{"type":["string","null"]},"event_id":{"type":["string","null"]},"properties":{"type":["object","null"],"additionalProperties":true},"timestamp":{"type":["string","null"]}},"description":"The `{ distinct_id?, event_id?, properties?, timestamp? }` body of\n`POST /v1/identify` and `/v1/group`. Unknown keys are ignored (the TS\nhandler reads the body loosely, unlike the strict batch schema)."}}}},"responses":{"202":{"description":"Accepted for processing","content":{"application/json":{"schema":{"type":"object","properties":{"accepted":{"type":"integer","format":"uint","minimum":0}},"required":["accepted"],"description":"`accepted` is `usize` to match what the handler already counted and\nserialized; narrowing it here would risk a panic on conversion for a wire\nvalue that has always been a plain JSON number."}}}},"400":{"description":"Malformed JSON or invalid payload","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer","format":"uint16","minimum":0,"maximum":65535},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message","error"]}}}},"401":{"description":"Missing or invalid project key","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer","format":"uint16","minimum":0,"maximum":65535},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message","error"]}}}},"403":{"description":"Project key belongs to a different region","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer","format":"uint16","minimum":0,"maximum":65535},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message","error"]}}}}}}},"/v1/group":{"post":{"summary":"Associate a user with a group","tags":["events"],"description":"Associates a distinct id with a group and its traits. A 202 means accepted for processing, not persisted.","security":[{"projectKey":[]}],"servers":[{"url":"https://eu.api.prodantix.com"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"distinct_id":{"type":["string","null"]},"event_id":{"type":["string","null"]},"properties":{"type":["object","null"],"additionalProperties":true},"timestamp":{"type":["string","null"]}},"description":"The `{ distinct_id?, event_id?, properties?, timestamp? }` body of\n`POST /v1/identify` and `/v1/group`. Unknown keys are ignored (the TS\nhandler reads the body loosely, unlike the strict batch schema)."}}}},"responses":{"202":{"description":"Accepted for processing","content":{"application/json":{"schema":{"type":"object","properties":{"accepted":{"type":"integer","format":"uint","minimum":0}},"required":["accepted"],"description":"`accepted` is `usize` to match what the handler already counted and\nserialized; narrowing it here would risk a panic on conversion for a wire\nvalue that has always been a plain JSON number."}}}},"400":{"description":"Malformed JSON or invalid payload","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer","format":"uint16","minimum":0,"maximum":65535},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message","error"]}}}},"401":{"description":"Missing or invalid project key","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer","format":"uint16","minimum":0,"maximum":65535},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message","error"]}}}},"403":{"description":"Project key belongs to a different region","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer","format":"uint16","minimum":0,"maximum":65535},"message":{"type":"string"},"error":{"type":"string"}},"required":["statusCode","message","error"]}}}}}}}},"components":{"schemas":{"EventEnvelope":{"type":"object","additionalProperties":false,"properties":{"context":{"anyOf":[{"$ref":"#/components/schemas/EventContext"},{"type":"null"}]},"distinct_id":{"type":"string"},"event_id":{"type":"string"},"event_name":{"type":"string"},"properties":{"type":"object","additionalProperties":true,"default":{}},"schema_version":{"type":"integer","format":"uint64","minimum":0},"session_id":{"type":["string","null"]},"timestamp":{"type":"string"}},"required":["distinct_id","event_id","event_name","schema_version","timestamp"],"description":"Ports `EventEnvelope` (`.strict()`). Shape (required fields, types, unknown\nkeys) is enforced by `serde`; `validate` layers on the Zod refinements."},"EventContext":{"type":"object","additionalProperties":false,"properties":{"locale":{"type":["string","null"]},"os":{"type":["string","null"]},"sdk":{"type":["string","null"]},"sdk_version":{"type":["string","null"]}},"description":"Ports `EventContext` (`.strict()`, all fields optional with max bounds)."}},"securitySchemes":{"projectKey":{"type":"http","scheme":"bearer","description":"A project API key presented as a Bearer token. Region-gated: a key issued in another region is rejected with 403."}}}}