{"openapi":"3.1.0","info":{"title":"trAIce Public API","version":"1.0.0","description":"Ingest AI usage evidence and ask workspace-scoped cost, margin, waste, recommendation, budget, and alert questions. The API is available on every plan; write operations use scoped credentials and explicit confirmation where required. Versioning, compatibility, deprecation, and rate-limit conventions are published at /developers/api-policy.","contact":{"name":"trAIce support","email":"support@runtraice.com","url":"https://www.runtraice.com/contact"},"license":{"name":"Proprietary API; open-source SDK","url":"https://github.com/runtraice/traice-sdk"}},"servers":[{"url":"https://www.runtraice.com","description":"Production"}],"externalDocs":{"description":"trAIce developer portal","url":"https://www.runtraice.com/developers"},"tags":[{"name":"Discovery","description":"Unauthenticated service and integration discovery."},{"name":"Telemetry","description":"Workspace-scoped AI usage ingestion."},{"name":"Ask trAIce","description":"Natural-language economic questions over workspace data."}],"paths":{"/api/v1/status":{"get":{"operationId":"getTraiceApiStatus","summary":"Discover the trAIce public API","description":"Returns stable links to the API schema, documentation, MCP resource, OAuth metadata, SDK, and CLI without authentication.","tags":["Discovery"],"security":[],"responses":{"200":{"description":"Public API discovery document.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiStatus"}}}},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/events":{"post":{"operationId":"ingestAiUsageEvents","summary":"Ingest one or more AI usage events","description":"Accepts a single event, an array, or an object containing an events array. Stable source and externalId pairs make retries idempotent.","tags":["Telemetry"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/UsageEvent"},{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/UsageEvent"}},{"type":"object","required":["events"],"properties":{"events":{"type":"array","minItems":1,"items":{"$ref":"#/components/schemas/UsageEvent"}}}}]}}}},"responses":{"200":{"description":"Events accepted or deduplicated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IngestResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/QuotaExceeded"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}},"security":[{"bearerAuth":[]}]}},"/api/v1/ask":{"post":{"operationId":"askTraiceEconomicQuestion","summary":"Ask a workspace-scoped AI cost question","description":"Answers questions about spend, customer or feature margin, waste, savings recommendations, budgets, and active alerts. Responses include the typed tool calls used and deep links where applicable.","tags":["Ask trAIce"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["question"],"properties":{"question":{"type":"string","minLength":1,"maxLength":500,"example":"Which feature had the highest AI cost this month?"}},"additionalProperties":false}}}},"responses":{"200":{"description":"Answer and supporting typed calls.","content":{"application/json":{"schema":{"type":"object","required":["answer","calls"],"properties":{"answer":{"type":"string"},"calls":{"type":"array","items":{"type":"object"}},"router":{"type":"string"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}},"security":[{"bearerAuth":[]}]}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"trAIce workspace API key or OAuth access token","description":"Create a scoped workspace key in the trAIce application. Interactive MCP clients should use OAuth discovery instead."}},"schemas":{"ApiStatus":{"type":"object","required":["service","status","openapi","docs","mcp","oauth","sdk","cli"],"properties":{"service":{"type":"string","const":"trAIce"},"status":{"type":"string","const":"available"},"openapi":{"type":"string","format":"uri"},"docs":{"type":"string","format":"uri"},"mcp":{"type":"string","format":"uri"},"oauth":{"type":"string","format":"uri"},"sdk":{"type":"string","format":"uri"},"cli":{"type":"string","format":"uri"}}},"UsageEvent":{"type":"object","properties":{"source":{"type":["string","null"],"maxLength":64},"externalId":{"type":["string","null"],"maxLength":256},"ts":{"oneOf":[{"type":"string","format":"date-time"},{"type":"number"}]},"provider":{"type":"string","maxLength":64},"model":{"type":"string","maxLength":128},"feature":{"type":["string","null"],"maxLength":128},"userId":{"type":["string","null"],"maxLength":128},"tenantId":{"type":["string","null"],"maxLength":128},"agentId":{"type":["string","null"],"maxLength":128},"workflowId":{"type":["string","null"],"maxLength":128},"runId":{"type":["string","null"],"maxLength":128},"stepId":{"type":["string","null"],"maxLength":128},"toolName":{"type":["string","null"],"maxLength":128},"outcome":{"type":["string","null"],"maxLength":32},"promptTokens":{"type":"integer","minimum":0},"outputTokens":{"type":"integer","minimum":0},"cacheReadTokens":{"type":"integer","minimum":0},"cacheWriteTokens":{"type":"integer","minimum":0},"costUsd":{"type":"number","minimum":0},"latencyMs":{"type":"integer","minimum":0},"status":{"type":"string","maxLength":32},"metadata":{"type":["object","null"],"additionalProperties":true}}},"IngestResult":{"type":"object","required":["accepted","deduplicated","dropped"],"properties":{"accepted":{"type":"integer","minimum":0},"deduplicated":{"type":"integer","minimum":0},"dropped":{"type":"integer","minimum":0},"plan":{"type":"string"}}},"Error":{"type":"object","required":["error","message","resolution"],"properties":{"error":{"type":"string","example":"invalid_api_key"},"message":{"type":"string","example":"The bearer credential is missing or invalid."},"resolution":{"type":"string","example":"Create a scoped key in trAIce and send it as Authorization: Bearer <key>."}},"additionalProperties":true}},"responses":{"BadRequest":{"description":"The request is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"The bearer credential is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The credential cannot perform this operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"QuotaExceeded":{"description":"The workspace monthly usage quota was exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"The requested workspace resource does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"PayloadTooLarge":{"description":"The request or event batch exceeds the documented limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"The current request or plan limit was exceeded.","headers":{"RateLimit":{"schema":{"type":"string"},"example":"\"default\";r=0;t=20","description":"Current quota state using the IETF RateLimit header draft."},"RateLimit-Limit":{"schema":{"type":"integer"}},"RateLimit-Remaining":{"schema":{"type":"integer"}},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Seconds until the active window resets."},"RateLimit-Policy":{"schema":{"type":"string"},"example":"\"default\";q=30;w=60"},"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"InternalError":{"description":"The request could not be completed because of an internal failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}