openapi: 3.1.0 info: title: FeedbackService API version: 1.0.0 security: - WorldMonitorKey: [] - ApiKeyHeader: [] servers: - url: https://api.worldmonitor.app paths: /api/feedback/v1/submit-report: post: parameters: - name: Idempotency-Key in: header description: Optional client-generated idempotency key. Retrying a POST with the same key and an identical request body replays the original response (only the status, body, and Content-Type are reproduced) instead of re-executing; reusing the key with a different body is rejected with 422. For mutations this avoids duplicating the side effect, while for batch-read POSTs it replays a cached snapshot that can be up to 24 hours stale. Keys are scoped per authenticated caller (falling back to the source IP for unauthenticated endpoints) and retained for 24 hours. required: false example: "4f8b9c2e-1a3d-4b6f-8e0a-2c5d7f9b1e34" schema: type: string minLength: 1 maxLength: 255 pattern: "^[\\x21-\\x7E]{1,255}$" tags: - FeedbackService summary: SubmitReport description: SubmitReport stores one structured report for human review and returns its id. Anonymous, tightly rate-limited, never acted on automatically. operationId: SubmitReport security: [] requestBody: content: application/json: example: "actual": "example" "clientName": "WorldMonitor Analyst" "expected": "example" "kind": "example" "requestId": "example-id" "summary": "Example WorldMonitor observation." "surface": "example" schema: $ref: '#/components/schemas/SubmitReportRequest' required: true responses: "200": description: Successful response headers: Idempotency-Key: schema: type: string description: The idempotency key echoed from the request. Present only when the client opted into idempotency. Idempotent-Replayed: schema: type: boolean description: true when this response was replayed from an earlier request with the same key, false on the first (original) request. Present only when the client opted into idempotency. content: application/json: example: "advisoryUrl": "https://example.com/worldmonitor" "notice": "example" "reportId": "example-id" "status": "example" schema: $ref: '#/components/schemas/SubmitReportResponse' "400": description: Validation error, invalid Idempotency-Key header, or malformed JSON request body content: application/json: schema: oneOf: - $ref: '#/components/schemas/ValidationError' - type: object required: - error - message properties: error: type: string message: type: string - $ref: '#/components/schemas/InvalidRequestBodyError' "409": description: A request with this Idempotency-Key is still being processed headers: Idempotency-Key: schema: type: string description: The idempotency key supplied by the client. Retry-After: schema: type: string description: Seconds to wait before retrying the in-flight request. content: application/json: schema: type: object required: - error - message properties: error: type: string message: type: string "422": description: The Idempotency-Key was already used with a different request body headers: Idempotency-Key: schema: type: string description: The idempotency key supplied by the client. content: application/json: schema: type: object required: - error - message properties: error: type: string message: type: string "429": description: Rate limit exceeded. headers: X-RateLimit-Limit: description: Maximum requests allowed in the active rate-limit window. schema: type: string X-RateLimit-Remaining: description: Requests remaining in the active rate-limit window. schema: type: string X-RateLimit-Reset: description: Unix epoch milliseconds when the active rate-limit window resets. schema: type: string Retry-After: description: Seconds to wait before retrying the request. schema: type: string content: application/json: schema: oneOf: - $ref: '#/components/schemas/Error' - $ref: '#/components/schemas/RateLimitError' default: description: Gateway or handler error response. content: application/json: schema: oneOf: - $ref: '#/components/schemas/Error' - $ref: '#/components/schemas/GatewayError' components: securitySchemes: WorldMonitorKey: type: apiKey in: header name: X-WorldMonitor-Key description: User-issued WorldMonitor API key. ApiKeyHeader: type: apiKey in: header name: X-Api-Key description: Alias header for the WorldMonitor API key (X-WorldMonitor-Key). schemas: JmespathProjectionError: description: Returned when a REST jmespath projection is invalid or exceeds the expression/output byte limits. properties: _jmespath_error: description: Projection error discriminator and details. type: string original_keys: description: Top-level keys or shape of the unprojected response. items: type: string type: array required: - _jmespath_error - original_keys type: object Error: type: object properties: message: type: string description: Error message (e.g., 'user not found', 'database connection failed') description: Error is returned when a handler encounters an error. It contains a simple error message that the developer can customize. InvalidRequestBodyError: type: object description: Returned when a JSON POST request body is empty or malformed. properties: message: type: string description: Invalid request body required: - message GatewayError: type: object description: Returned by gateway infrastructure errors before an RPC handler runs, such as origin, routing, method, authentication, or quota checks. properties: error: oneOf: - type: string - type: object additionalProperties: true description: Gateway error reason or structured gateway failure details. required: - error RateLimitError: type: object description: Returned when a gateway or handler rate limit rejects the request. properties: error: type: string description: Human-readable rate-limit failure reason. required: - error FieldViolation: type: object properties: field: type: string description: The field path that failed validation (e.g., 'user.email' for nested fields). For header validation, this will be the header name (e.g., 'X-API-Key') description: type: string description: Human-readable description of the validation violation (e.g., 'must be a valid email address', 'required field missing') required: - field - description description: FieldViolation describes a single validation error for a specific field. ValidationError: type: object properties: violations: type: array items: $ref: '#/components/schemas/FieldViolation' description: List of validation violations required: - violations description: ValidationError is returned when request validation fails. It contains a list of field violations describing what went wrong. SubmitReportRequest: type: object properties: kind: type: string maxLength: 32 description: bug | missing_capability | data_quality | security. surface: type: string maxLength: 200 description: 'What the report is about: an MCP tool name (get_market_data), an API path (/api/market/v1/list-market-quotes), or a short label. A name that does not exist yet is fine.' summary: type: string maxLength: 300 description: One-line description of the problem. expected: type: string maxLength: 2000 description: What you expected to happen. actual: type: string maxLength: 2000 description: What happened instead. requestId: type: string maxLength: 128 description: Request id of the failing call (the x-vercel-id response header, or data.requestId in an MCP error), so the report joins to our logs. clientName: type: string maxLength: 80 description: Name of the calling client or agent, for display only. required: - kind - summary description: 'SubmitReportRequest is one structured report from an agent. Do not include credentials: they are redacted before storage. For a security report, do not include exploit details; use the private advisory form.' SubmitReportResponse: type: object properties: reportId: type: string description: Report id to quote in any follow-up. status: type: string description: received, or private for a security report. advisoryUrl: type: string description: 'Security reports only: the private advisory form, where exploit details belong.' notice: type: string description: 'Security reports only: a reminder not to send exploit details through this channel.' description: SubmitReportResponse acknowledges a stored report.