{
  "openapi": "3.1.0",
  "info": {
    "title": "VERIS API",
    "version": "1.0.0",
    "description": "Managed AI request routing. One endpoint, multi-provider fallback, cost + latency policies.  **Versioning.** VERIS guarantees backwards compatibility within a major version. `/v1` endpoints remain stable; breaking changes ship in `/v2`. Additive changes (new optional fields, new capabilities) may appear in `/v1` at any time.  **Canonical examples.** Every example below uses the `resume-parser` application from the VERIS canonical dataset. Replace with your own application slug.  **Errors.** Every non-2xx response uses the shape `{ error: { code, message, meta? } }`. See the API docs page for the full error reference."
  },
  "servers": [
    {
      "url": "https://veris.digital/api/v1",
      "description": "Production"
    },
    {
      "url": "/api/v1",
      "description": "Same-origin"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "paths": {
    "/api/v1/health": {
      "get": {
        "summary": "Reachability probe",
        "description": "Auth-free, side-effect-free health check. Returns platform status, API version, and the list of live capabilities.",
        "security": [],
        "responses": {
          "200": {
            "description": "Platform reachable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                }
              }
            }
          }
        }
      },
      "options": {
        "summary": "CORS preflight",
        "responses": {
          "204": {
            "description": "No content"
          }
        }
      }
    },
    "/api/v1/chat": {
      "post": {
        "summary": "Route and execute a chat completion",
        "description": "Selects a provider + model based on the application's routing policy, executes the request, records the ledger entry, and returns the response.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChatRequest"
              },
              "examples": {
                "simple": {
                  "summary": "Simple prompt",
                  "value": {
                    "application": "resume-parser",
                    "environment": "production",
                    "workload": "extract",
                    "input": "Extract name, email, and years of experience from this resume."
                  }
                },
                "messages": {
                  "summary": "Multi-turn conversation",
                  "value": {
                    "application": "resume-parser",
                    "environment": "production",
                    "workload": "extract",
                    "messages": [
                      {
                        "role": "system",
                        "content": "You are a resume parser. Reply with JSON."
                      },
                      {
                        "role": "user",
                        "content": "Extract name, email, and years of experience from this resume."
                      }
                    ],
                    "maxCostUsd": 0.05
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful completion",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChatResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/BudgetBlocked"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/NoCandidates"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "options": {
        "summary": "CORS preflight",
        "responses": {
          "204": {
            "description": "No content"
          }
        }
      }
    },
    "/api/v1/chat/completions": {
      "post": {
        "summary": "OpenAI-compatible chat completions",
        "description": "Genuine OpenAI-compatible endpoint. The body stays a standard OpenAI body; VERIS routing context travels in `x-veris-*` headers. `model` always means a model: send `veris-auto` to let VERIS choose, or name a real model. It never names an application. Supports streaming, tools, structured output, image input and `provider_options`. Any standard field VERIS cannot honour returns a 400 naming the field, never a silent no-op. Routing, budgets, fallback and evidence are identical to `/api/v1/chat`.",
        "parameters": [
          {
            "name": "x-veris-application",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "example": "resume-parser"
            },
            "description": "Application slug. Defaults to the application the key is bound to."
          },
          {
            "name": "x-veris-environment",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "example": "production"
            },
            "description": "Environment name. Defaults to the key's environment."
          },
          {
            "name": "x-veris-workload",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "example": "extract"
            },
            "description": "Workload tag for routing and cost attribution."
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Replays the stored response for an identical request. Rejected with 400 on streaming requests, because a streamed response cannot be replayed."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OpenAiChatRequest"
              },
              "examples": {
                "simple": {
                  "summary": "Let VERIS choose the model",
                  "value": {
                    "model": "veris-auto",
                    "messages": [
                      {
                        "role": "user",
                        "content": "Extract name, email, and years of experience from this resume."
                      }
                    ]
                  }
                },
                "streaming": {
                  "summary": "Stream the response",
                  "value": {
                    "model": "veris-auto",
                    "stream": true,
                    "messages": [
                      {
                        "role": "user",
                        "content": "Extract name, email, and years of experience from this resume."
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Chat completion. With `stream: true` the response is `text/event-stream` carrying OpenAI-shaped chunks, a final `finish_reason`, and a terminating `[DONE]`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OpenAiChatResponse"
                }
              },
              "text/event-stream": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/BudgetBlocked"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/NoCandidates"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "options": {
        "summary": "CORS preflight",
        "responses": {
          "204": {
            "description": "No content"
          }
        }
      }
    },
    "/api/v1/embeddings": {
      "post": {
        "summary": "Generate embeddings",
        "description": "OpenAI-compatible embeddings endpoint. The router selects a provider; the embed executor owns the capability-specific API call.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EmbedRequest"
              },
              "examples": {
                "singleInput": {
                  "summary": "Embed a single string",
                  "value": {
                    "application": "resume-parser",
                    "environment": "production",
                    "input": "Senior software engineer with 8 years of backend experience."
                  }
                },
                "batchInput": {
                  "summary": "Embed a batch of strings",
                  "value": {
                    "application": "resume-parser",
                    "environment": "production",
                    "input": [
                      "Senior software engineer with 8 years of backend experience.",
                      "Junior frontend developer with React experience."
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Vectors returned",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmbedResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/BudgetBlocked"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/NoCandidates"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "options": {
        "summary": "CORS preflight",
        "responses": {
          "204": {
            "description": "No content"
          }
        }
      }
    },
    "/api/v1/images/generations": {
      "post": {
        "summary": "Generate an image",
        "description": "Synchronous image generation. The body is provider-neutral: a prompt plus generic output controls. Artifacts are returned as described objects — inline bytes when the provider returned bytes, or a provider-managed URL that expires.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ImageRequest"
              },
              "examples": {
                "basic": {
                  "summary": "One image from a prompt",
                  "value": {
                    "application": "resume-parser",
                    "environment": "production",
                    "prompt": "A watercolor fox in a snowy forest",
                    "size": "1024x1024"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Image generated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImageResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/BudgetBlocked"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/NoCandidates"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "options": {
        "summary": "CORS preflight",
        "responses": {
          "204": {
            "description": "No content"
          }
        }
      }
    },
    "/api/v1/rerank": {
      "post": {
        "summary": "Rerank a candidate list",
        "description": "Synchronous relevance reranking. Send a query and the candidate documents; VERIS returns the documents ordered by relevance, descending. `index` is always the position in the request `documents` array, so the ranking can be joined back onto your own corpus. Not generally available yet: rerank requires a model VERIS has verified for the rerank capability, and requests are rejected with an explanation until one is connected.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RerankRequest"
              },
              "examples": {
                "basic": {
                  "summary": "Rank three candidates",
                  "value": {
                    "application": "resume-parser",
                    "environment": "production",
                    "model": "veris-auto",
                    "query": "Which candidate has backend experience?",
                    "documents": [
                      "Senior backend engineer, 8 years of Go and Postgres.",
                      "Graphic designer with a focus on brand identity.",
                      "Frontend engineer who has shipped some Node services."
                    ],
                    "top_n": 2
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Documents ranked",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RerankResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/BudgetBlocked"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/NoCandidates"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "options": {
        "summary": "CORS preflight",
        "responses": {
          "204": {
            "description": "No content"
          }
        }
      }
    },
    "/api/v1/document/ocr": {
      "post": {
        "summary": "Read the text of a document",
        "description": "Synchronous document OCR. Send one document as inline base64, as a permitted https url, or as a multipart upload under `file`, and VERIS returns the text page by page in document order. Billing is by page: the response reports how many pages were read and how many the provider could not read, and reports the provider's own charge in the currency the provider quoted rather than converting it. Only models VERIS has verified for document OCR can serve this route; a request that no verified model can satisfy is rejected with an explanation instead of being sent to a text model.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DocumentOcrRequest"
              },
              "examples": {
                "inline": {
                  "summary": "Inline PDF bytes",
                  "value": {
                    "application": "resume-parser",
                    "environment": "production",
                    "model": "veris-auto",
                    "document": {
                      "source": "inline",
                      "mime_type": "application/pdf",
                      "filename": "invoice.pdf",
                      "data": "JVBERi0xLjQKJ..."
                    }
                  }
                },
                "url": {
                  "summary": "Permitted https url",
                  "value": {
                    "application": "resume-parser",
                    "environment": "production",
                    "document": {
                      "source": "url",
                      "mime_type": "application/pdf",
                      "url": "https://example.com/invoice.pdf"
                    },
                    "pages": {
                      "from": 1,
                      "to": 2
                    }
                  }
                }
              }
            },
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "application",
                  "file"
                ],
                "properties": {
                  "application": {
                    "type": "string"
                  },
                  "environment": {
                    "type": "string"
                  },
                  "workload": {
                    "type": "string"
                  },
                  "model": {
                    "type": "string"
                  },
                  "language": {
                    "type": "string"
                  },
                  "mime_type": {
                    "type": "string"
                  },
                  "file": {
                    "type": "string",
                    "format": "binary"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Document read",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentOcrResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/BudgetBlocked"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/NoCandidates"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "options": {
        "summary": "CORS preflight",
        "responses": {
          "204": {
            "description": "No content"
          }
        }
      }
    },
    "/api/v1/document/extract": {
      "post": {
        "summary": "Extract fields from a document",
        "description": "Schema-directed document extraction. Name the fields you want in `schema` and send one document as inline base64, as a permitted https url, or as a multipart upload under `file`. VERIS returns the resolved values keyed by your field names, plus per-value evidence — the provider's confidence and the source pages — whenever the provider reports it. A field the provider could not resolve is absent rather than guessed. Billing is by page, and the provider's own charge is reported in the currency it quoted rather than converted. Only models VERIS has verified for document extraction can serve this route; a request that no verified model can satisfy is rejected with an explanation.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DocumentExtractRequest"
              },
              "examples": {
                "inline": {
                  "summary": "Inline PDF bytes",
                  "value": {
                    "application": "resume-parser",
                    "environment": "production",
                    "model": "veris-auto",
                    "document": {
                      "source": "inline",
                      "mime_type": "application/pdf",
                      "filename": "invoice.pdf",
                      "data": "JVBERi0xLjQKJ..."
                    },
                    "schema": {
                      "invoice_number": "string",
                      "total": "number"
                    }
                  }
                },
                "url": {
                  "summary": "Permitted https url",
                  "value": {
                    "application": "resume-parser",
                    "environment": "production",
                    "document": {
                      "source": "url",
                      "mime_type": "application/pdf",
                      "url": "https://example.com/invoice.pdf"
                    },
                    "schema": {
                      "document_title": "string"
                    }
                  }
                }
              }
            },
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "application",
                  "file",
                  "schema"
                ],
                "properties": {
                  "application": {
                    "type": "string"
                  },
                  "environment": {
                    "type": "string"
                  },
                  "workload": {
                    "type": "string"
                  },
                  "model": {
                    "type": "string"
                  },
                  "language": {
                    "type": "string"
                  },
                  "mime_type": {
                    "type": "string"
                  },
                  "schema": {
                    "type": "string",
                    "description": "The extraction schema, as a JSON string."
                  },
                  "file": {
                    "type": "string",
                    "format": "binary"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Fields extracted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentExtractResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/BudgetBlocked"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/NoCandidates"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "options": {
        "summary": "CORS preflight",
        "responses": {
          "204": {
            "description": "No content"
          }
        }
      }
    },
    "/api/v1/audio/speech": {
      "post": {
        "summary": "Synthesize speech",
        "description": "Synchronous text to speech. Returns the audio as a described artifact alongside the routing decision, request id and cost provenance, rather than as a bare audio body.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SpeechRequest"
              },
              "examples": {
                "basic": {
                  "summary": "Speak a sentence",
                  "value": {
                    "application": "resume-parser",
                    "environment": "production",
                    "input": "Your resume has been processed.",
                    "response_format": "wav"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Audio generated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SpeechResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/BudgetBlocked"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/NoCandidates"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "options": {
        "summary": "CORS preflight",
        "responses": {
          "204": {
            "description": "No content"
          }
        }
      }
    },
    "/api/v1/audio/transcriptions": {
      "post": {
        "summary": "Transcribe audio",
        "description": "Synchronous speech to text. Accepts `multipart/form-data` with a `file` field (the shape OpenAI clients already send) or JSON carrying base64 audio in `audio_b64`. Inline audio is limited to 20 MB per request.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TranscriptionRequest"
              },
              "examples": {
                "base64": {
                  "summary": "Base64 audio",
                  "value": {
                    "application": "resume-parser",
                    "environment": "production",
                    "audio_b64": "UklGRi4AAABXQVZF…",
                    "audio_mime_type": "audio/wav",
                    "language": "en-IN"
                  }
                }
              }
            },
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "application",
                  "file"
                ],
                "properties": {
                  "application": {
                    "type": "string",
                    "example": "resume-parser"
                  },
                  "environment": {
                    "type": "string",
                    "example": "production"
                  },
                  "workload": {
                    "type": "string"
                  },
                  "model": {
                    "type": "string"
                  },
                  "language": {
                    "type": "string",
                    "example": "en-IN"
                  },
                  "file": {
                    "type": "string",
                    "format": "binary"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Transcript returned",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TranscriptionResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/BudgetBlocked"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/NoCandidates"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "options": {
        "summary": "CORS preflight",
        "responses": {
          "204": {
            "description": "No content"
          }
        }
      }
    },
    "/api/v1/video/generations": {
      "post": {
        "summary": "Submit a video generation job",
        "description": "Asynchronous. Video runs longer than a request should be held open, so VERIS records the job durably and answers `202` with a job id. Poll `GET /api/v1/video/generations/{jobId}` for the result. Send an `Idempotency-Key` header to make a retried submission return the same job instead of a second one.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Retry-safe submission key, scoped to this application and capability."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VideoRequest"
              },
              "examples": {
                "basic": {
                  "summary": "Six seconds of video",
                  "value": {
                    "application": "resume-parser",
                    "environment": "production",
                    "prompt": "A slow dolly across a snowy forest at dawn",
                    "duration_seconds": 6,
                    "size": "1280x720"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Job accepted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VideoJobAccepted"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/BudgetBlocked"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "options": {
        "summary": "CORS preflight",
        "responses": {
          "204": {
            "description": "No content"
          }
        }
      }
    },
    "/api/v1/video/generations/{jobId}": {
      "get": {
        "summary": "Read a video generation job",
        "description": "Returns the job's current state. `queued` and `running` mean keep polling; `completed` carries the artifacts; `failed` carries the canonical error code and message. Jobs are readable only by the organisation that submitted them.",
        "parameters": [
          {
            "name": "jobId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Job state",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VideoJob"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "options": {
        "summary": "CORS preflight",
        "responses": {
          "204": {
            "description": "No content"
          }
        }
      }
    },
    "/api/v1/ingestion/fingerprint": {
      "post": {
        "summary": "Check or register an ingestion fingerprint",
        "description": "Document ingestion deduplication. Ask whether this exact document has already been ingested for this application before you parse, chunk and embed it. Identity is document hash + parser version + chunking version + embedding model + dimensions + index, so changing any one of them is a different artifact. Reuse is exact equivalence, never similarity, and never crosses applications. VERIS stores the hash and the versions, never document content.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "application",
                  "document_hash"
                ],
                "properties": {
                  "application": {
                    "type": "string",
                    "description": "Application slug."
                  },
                  "environment": {
                    "type": "string"
                  },
                  "workload": {
                    "type": "string",
                    "description": "Embedding index name. Defaults to `embed`."
                  },
                  "document_hash": {
                    "type": "string",
                    "description": "Your content hash of the source document."
                  },
                  "parser_version": {
                    "type": "string",
                    "default": "v1"
                  },
                  "chunking_version": {
                    "type": "string",
                    "default": "v1"
                  },
                  "model": {
                    "type": "string",
                    "description": "Only needed before an embedding index is locked."
                  },
                  "dimensions": {
                    "type": "integer"
                  },
                  "artifact_ref": {
                    "type": "string",
                    "description": "Your reference to the ingested artifact. Send it to register a document you just ingested."
                  },
                  "chunk_count": {
                    "type": "integer"
                  },
                  "ttl_days": {
                    "type": "integer"
                  }
                }
              },
              "examples": {
                "check": {
                  "summary": "Check before ingesting",
                  "value": {
                    "application": "resume-parser",
                    "document_hash": "sha256:2f1c9b4e8a0d5f37c6e2b91a4d8f0c73e5a6b1d92f84c0e7a3b5d6f18c9e2740",
                    "parser_version": "pdf-2",
                    "chunking_version": "v3"
                  }
                },
                "register": {
                  "summary": "Register after ingesting",
                  "value": {
                    "application": "resume-parser",
                    "document_hash": "sha256:2f1c9b4e8a0d5f37c6e2b91a4d8f0c73e5a6b1d92f84c0e7a3b5d6f18c9e2740",
                    "parser_version": "pdf-2",
                    "chunking_version": "v3",
                    "artifact_ref": "vector-store/doc_8814",
                    "chunk_count": 42
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Reuse verdict",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "reused": {
                      "type": "boolean"
                    },
                    "registered": {
                      "type": "boolean"
                    },
                    "fingerprint": {
                      "type": "string"
                    },
                    "artifact_ref": {
                      "type": "string"
                    },
                    "chunk_count": {
                      "type": "integer",
                      "nullable": true
                    },
                    "first_ingested_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "reuse_count": {
                      "type": "integer"
                    },
                    "model": {
                      "type": "string"
                    },
                    "dimensions": {
                      "type": "integer"
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "options": {
        "summary": "CORS preflight",
        "responses": {
          "204": {
            "description": "No content"
          }
        }
      }
    },
    "/api/v1/models": {
      "get": {
        "summary": "List routable models",
        "description": "OpenAI-compatible model listing scoped to the calling key. Returns the request-time candidate pool for the key's workspace and application using the same eligibility truth as routing. There is no global catalogue and no cross-tenant listing.",
        "parameters": [
          {
            "name": "application",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Application slug. Defaults to the application the key is bound to."
          },
          {
            "name": "environment",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Environment name. Defaults to the key's environment."
          }
        ],
        "responses": {
          "200": {
            "description": "Model list",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ModelList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "options": {
        "summary": "CORS preflight",
        "responses": {
          "204": {
            "description": "No content"
          }
        }
      }
    },
    "/api/v1/reindex/{jobId}": {
      "post": {
        "summary": "Report re-index progress",
        "description": "Progress callback for a VERIS-driven re-embedding run. The application reports how far its re-index has gotten; when it reports `completed`, VERIS flips the embedding index lock to the new model. The job must belong to the organization the API key was issued for.",
        "parameters": [
          {
            "name": "jobId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Re-index job identifier delivered by VERIS when the job was dispatched."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReindexProgressRequest"
              },
              "examples": {
                "progress": {
                  "summary": "Report partial progress",
                  "value": {
                    "status": "running",
                    "itemsDone": 4200,
                    "itemsTotal": 18000
                  }
                },
                "completed": {
                  "summary": "Report completion",
                  "value": {
                    "status": "completed",
                    "itemsDone": 18000,
                    "itemsTotal": 18000,
                    "qualityAfter": 0.94
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Progress accepted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReindexProgressResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "Progress conflicts with the job's current state",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "options": {
        "summary": "CORS preflight",
        "responses": {
          "204": {
            "description": "No content"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "VERIS API key. New keys use the `veris_` prefix; legacy `aios_` keys remain accepted for backwards compatibility. Create keys under Developer → API keys."
      }
    },
    "responses": {
      "InvalidRequest": {
        "description": "Body failed validation",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing, malformed, revoked, or expired API key",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "BudgetBlocked": {
        "description": "Blocked by a spend control. Either the application budget cap was reached (`budget_blocked`), or the provider reports no cost for this capability and the daily unreported-cost operation ceiling was reached (`unknown_cost_limit`).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "NotFound": {
        "description": "Application or environment slug not found",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "NoCandidates": {
        "description": "No provider satisfies the routing policy",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Too many requests",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "InternalError": {
        "description": "Upstream provider failure after all fallbacks",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      }
    },
    "schemas": {
      "Artifact": {
        "type": "object",
        "description": "One piece of non-text output. `delivery` says how to read it: `inline` carries base64 bytes in `b64`, `url` carries a provider-managed link in `url` that expires — download it if you need to keep it.",
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "image",
              "audio",
              "video"
            ]
          },
          "mime_type": {
            "type": "string",
            "example": "image/png"
          },
          "delivery": {
            "type": "string",
            "enum": [
              "inline",
              "url"
            ]
          },
          "b64": {
            "type": "string",
            "nullable": true
          },
          "url": {
            "type": "string",
            "nullable": true
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true
          }
        }
      },
      "CapabilityUsage": {
        "type": "object",
        "description": "What was billed and how confident VERIS is about the amount. `cost_provenance` is `reported` when the provider returned the charge, `derived` when VERIS computed it from published rates, and `unavailable` when the provider reports nothing — in which case `cost_usd` is null, never zero.",
        "properties": {
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "number"
            },
            "example": {
              "images": 1
            }
          },
          "cost_usd": {
            "type": "number",
            "nullable": true,
            "example": 0.0032
          },
          "cost_provenance": {
            "type": "string",
            "enum": [
              "reported",
              "derived",
              "unavailable"
            ]
          }
        }
      },
      "CapabilityRequestBase": {
        "type": "object",
        "required": [
          "application"
        ],
        "properties": {
          "application": {
            "type": "string",
            "description": "Application slug or id. `project` is accepted as an alias.",
            "example": "resume-parser"
          },
          "environment": {
            "type": "string",
            "example": "production"
          },
          "workload": {
            "type": "string",
            "description": "Optional workload key; routing policy is resolved from it."
          },
          "model": {
            "type": "string",
            "description": "Optional explicit model. Omit it to let VERIS route across your configured providers."
          },
          "provider_options": {
            "type": "object",
            "additionalProperties": true,
            "description": "Namespaced provider-specific options, keyed by provider slug. Passed through untouched."
          }
        }
      },
      "ImageRequest": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CapabilityRequestBase"
          },
          {
            "type": "object",
            "required": [
              "prompt"
            ],
            "properties": {
              "prompt": {
                "type": "string",
                "example": "A watercolor fox in a snowy forest"
              },
              "negative_prompt": {
                "type": "string"
              },
              "size": {
                "type": "string",
                "example": "1024x1024"
              },
              "n": {
                "type": "integer",
                "minimum": 1,
                "maximum": 4,
                "default": 1
              },
              "seed": {
                "type": "integer"
              }
            }
          }
        ]
      },
      "CapabilityResponseBase": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "VERIS request id, matching Request History."
          },
          "capability": {
            "type": "string",
            "example": "image"
          },
          "model": {
            "type": "string",
            "description": "Model VERIS actually executed."
          },
          "provider": {
            "type": "string"
          },
          "usage": {
            "$ref": "#/components/schemas/CapabilityUsage"
          }
        }
      },
      "ImageResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CapabilityResponseBase"
          },
          {
            "type": "object",
            "properties": {
              "artifacts": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Artifact"
                }
              }
            }
          }
        ]
      },
      "RerankRequest": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CapabilityRequestBase"
          },
          {
            "type": "object",
            "required": [
              "query",
              "documents"
            ],
            "properties": {
              "query": {
                "type": "string",
                "maxLength": 8000,
                "example": "Which candidate has backend experience?"
              },
              "documents": {
                "type": "array",
                "minItems": 1,
                "maxItems": 1000,
                "items": {
                  "type": "string"
                },
                "description": "Candidate documents in your own order. That order defines `index`."
              },
              "top_n": {
                "type": "integer",
                "minimum": 1,
                "description": "How many ranked results to return. Must not exceed `documents.length`."
              },
              "return_documents": {
                "type": "boolean",
                "default": false,
                "description": "Echo the document text back on each result."
              }
            }
          }
        ]
      },
      "RerankResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CapabilityResponseBase"
          },
          {
            "type": "object",
            "properties": {
              "object": {
                "type": "string",
                "example": "rerank.results"
              },
              "results": {
                "type": "array",
                "description": "Ordered by `relevance_score`, descending.",
                "items": {
                  "type": "object",
                  "required": [
                    "index",
                    "relevance_score"
                  ],
                  "properties": {
                    "index": {
                      "type": "integer",
                      "description": "Position of this document in the request `documents` array."
                    },
                    "relevance_score": {
                      "type": "number"
                    },
                    "document": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        ]
      },
      "DocumentInput": {
        "type": "object",
        "required": [
          "source",
          "mime_type"
        ],
        "description": "One document. `source` decides which payload field is required: inline needs `data`, url needs `url`, artifact needs `artifact_ref`. A url must be https and pass the platform's fetch policy.",
        "properties": {
          "source": {
            "type": "string",
            "enum": [
              "inline",
              "url",
              "artifact"
            ]
          },
          "mime_type": {
            "type": "string",
            "example": "application/pdf"
          },
          "filename": {
            "type": "string"
          },
          "data": {
            "type": "string",
            "description": "Base64 bytes. Inline documents only."
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "artifact_ref": {
            "type": "string"
          }
        }
      },
      "DocumentOcrRequest": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CapabilityRequestBase"
          },
          {
            "type": "object",
            "required": [
              "document"
            ],
            "properties": {
              "document": {
                "$ref": "#/components/schemas/DocumentInput"
              },
              "pages": {
                "type": "object",
                "description": "Optional 1-based inclusive page window.",
                "required": [
                  "from",
                  "to"
                ],
                "properties": {
                  "from": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "to": {
                    "type": "integer",
                    "minimum": 1
                  }
                }
              },
              "language": {
                "type": "string",
                "description": "Expected document language, when you know it."
              }
            }
          }
        ]
      },
      "DocumentOcrResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CapabilityResponseBase"
          },
          {
            "type": "object",
            "properties": {
              "object": {
                "type": "string",
                "example": "document.ocr"
              },
              "pages": {
                "type": "array",
                "description": "Pages in document order. A page that could not be read has empty text.",
                "items": {
                  "type": "object",
                  "required": [
                    "index",
                    "text"
                  ],
                  "properties": {
                    "index": {
                      "type": "integer"
                    },
                    "text": {
                      "type": "string"
                    },
                    "layout": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                }
              },
              "text": {
                "type": "string",
                "description": "Convenience join of the non-empty page texts, in page order."
              },
              "page_count": {
                "type": "integer"
              },
              "pages_succeeded": {
                "type": "integer"
              },
              "pages_failed": {
                "type": "integer"
              },
              "outcome": {
                "type": "string",
                "enum": [
                  "completed",
                  "partially_completed"
                ]
              },
              "provider_cost": {
                "type": "number",
                "description": "The provider's own charge, in the currency it quoted. Not converted."
              },
              "provider_currency": {
                "type": "string",
                "nullable": true,
                "example": "INR"
              }
            }
          }
        ]
      },
      "DocumentExtractRequest": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CapabilityRequestBase"
          },
          {
            "type": "object",
            "required": [
              "document",
              "schema"
            ],
            "properties": {
              "document": {
                "$ref": "#/components/schemas/DocumentInput"
              },
              "schema": {
                "type": "object",
                "additionalProperties": true,
                "description": "The fields you want back, as a name -> type or description map. Field names in the response are exactly these names.",
                "example": {
                  "invoice_number": "string",
                  "total": "number"
                }
              },
              "pages": {
                "type": "object",
                "description": "Optional 1-based inclusive page window.",
                "required": [
                  "from",
                  "to"
                ],
                "properties": {
                  "from": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "to": {
                    "type": "integer",
                    "minimum": 1
                  }
                }
              },
              "language": {
                "type": "string",
                "description": "Expected document language, when you know it."
              }
            }
          }
        ]
      },
      "DocumentExtractResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CapabilityResponseBase"
          },
          {
            "type": "object",
            "properties": {
              "object": {
                "type": "string",
                "example": "document.extract"
              },
              "fields": {
                "type": "object",
                "additionalProperties": true,
                "description": "Resolved values keyed by your requested field names. A field the provider could not resolve is absent."
              },
              "field_evidence": {
                "type": "object",
                "description": "What is known about each value, keyed by the same dotted field path used in `fields`. Present only where the provider reported something.",
                "additionalProperties": {
                  "type": "object",
                  "properties": {
                    "confidence": {
                      "type": "number"
                    },
                    "source_pages": {
                      "type": "array",
                      "items": {
                        "type": "integer"
                      }
                    }
                  }
                }
              },
              "page_count": {
                "type": "integer"
              },
              "pages_succeeded": {
                "type": "integer"
              },
              "pages_failed": {
                "type": "integer"
              },
              "outcome": {
                "type": "string",
                "enum": [
                  "completed",
                  "partially_completed"
                ]
              },
              "provider_cost": {
                "type": "number",
                "description": "The provider's own charge, in the currency it quoted. Not converted."
              },
              "provider_currency": {
                "type": "string",
                "nullable": true,
                "example": "INR"
              }
            }
          }
        ]
      },
      "SpeechRequest": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CapabilityRequestBase"
          },
          {
            "type": "object",
            "required": [
              "input"
            ],
            "properties": {
              "input": {
                "type": "string",
                "example": "Your resume has been processed."
              },
              "voice": {
                "type": "string"
              },
              "language": {
                "type": "string",
                "example": "en-IN"
              },
              "speed": {
                "type": "number",
                "example": 1
              },
              "response_format": {
                "type": "string",
                "enum": [
                  "wav",
                  "mp3",
                  "ogg"
                ],
                "default": "wav"
              }
            }
          }
        ]
      },
      "SpeechResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CapabilityResponseBase"
          },
          {
            "type": "object",
            "properties": {
              "artifacts": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Artifact"
                }
              }
            }
          }
        ]
      },
      "TranscriptionRequest": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CapabilityRequestBase"
          },
          {
            "type": "object",
            "description": "Send either `audio_b64` with `audio_mime_type`, or use `multipart/form-data` with a `file` field.",
            "properties": {
              "audio_b64": {
                "type": "string"
              },
              "audio_mime_type": {
                "type": "string",
                "example": "audio/wav"
              },
              "language": {
                "type": "string",
                "example": "en-IN"
              },
              "prompt": {
                "type": "string",
                "description": "Optional biasing hint."
              }
            }
          }
        ]
      },
      "TranscriptionResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CapabilityResponseBase"
          },
          {
            "type": "object",
            "properties": {
              "text": {
                "type": "string"
              },
              "language": {
                "type": "string",
                "nullable": true
              },
              "segments": {
                "type": "array",
                "nullable": true,
                "items": {
                  "type": "object",
                  "properties": {
                    "text": {
                      "type": "string"
                    },
                    "start": {
                      "type": "number",
                      "nullable": true
                    },
                    "end": {
                      "type": "number",
                      "nullable": true
                    }
                  }
                }
              }
            }
          }
        ]
      },
      "VideoRequest": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CapabilityRequestBase"
          },
          {
            "type": "object",
            "required": [
              "prompt"
            ],
            "properties": {
              "prompt": {
                "type": "string",
                "example": "A slow dolly across a snowy forest at dawn"
              },
              "negative_prompt": {
                "type": "string"
              },
              "duration_seconds": {
                "type": "number",
                "example": 6
              },
              "size": {
                "type": "string",
                "example": "1280x720"
              },
              "seed": {
                "type": "integer"
              }
            }
          }
        ]
      },
      "VideoJobAccepted": {
        "type": "object",
        "properties": {
          "job_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "queued"
            ]
          },
          "capability": {
            "type": "string",
            "example": "video"
          },
          "poll_url": {
            "type": "string",
            "example": "/api/v1/video/generations/6f1c1f0e-1a5e-4b6c-9a2f-6a1b0c2d3e4f"
          }
        }
      },
      "VideoJob": {
        "type": "object",
        "properties": {
          "job_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "running",
              "completed",
              "failed"
            ]
          },
          "capability": {
            "type": "string",
            "example": "video"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "completed_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "request_id": {
            "type": "string",
            "nullable": true,
            "description": "VERIS request id once the job has executed."
          },
          "model": {
            "type": "string",
            "nullable": true
          },
          "provider": {
            "type": "string",
            "nullable": true
          },
          "artifacts": {
            "type": "array",
            "nullable": true,
            "items": {
              "$ref": "#/components/schemas/Artifact"
            }
          },
          "usage": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CapabilityUsage"
              }
            ],
            "nullable": true
          },
          "error": {
            "type": "object",
            "nullable": true,
            "properties": {
              "code": {
                "type": "string",
                "example": "upstream_error"
              },
              "message": {
                "type": "string"
              }
            }
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string",
                "description": "Stable machine-readable code. See the API docs page for the reference table.",
                "example": "invalid_api_key"
              },
              "message": {
                "type": "string",
                "example": "The API key is invalid."
              },
              "meta": {
                "type": "object",
                "additionalProperties": true,
                "description": "Optional context (routing candidates, budget delta, etc.)"
              }
            }
          }
        }
      },
      "HealthResponse": {
        "type": "object",
        "required": [
          "status",
          "version",
          "capabilities",
          "timestamp"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ok"
            ]
          },
          "version": {
            "type": "string",
            "example": "1.0.0"
          },
          "capabilities": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "example": [
              "chat",
              "embed"
            ]
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ModelList": {
        "type": "object",
        "required": [
          "object",
          "data"
        ],
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "list"
            ]
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "id",
                "object",
                "owned_by"
              ],
              "properties": {
                "id": {
                  "type": "string",
                  "example": "gpt-4.1-nano"
                },
                "object": {
                  "type": "string",
                  "enum": [
                    "model"
                  ]
                },
                "created": {
                  "type": "integer"
                },
                "owned_by": {
                  "type": "string",
                  "example": "openai"
                }
              }
            }
          }
        }
      },
      "ReindexProgressRequest": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "running",
              "verifying",
              "completed",
              "failed"
            ],
            "description": "Current state of the re-embedding run."
          },
          "itemsDone": {
            "type": "integer",
            "minimum": 0
          },
          "itemsTotal": {
            "type": "integer",
            "minimum": 0
          },
          "qualityAfter": {
            "type": "number",
            "minimum": 0,
            "maximum": 1,
            "description": "Optional post-migration quality score, when the application measures one."
          },
          "error": {
            "type": "string",
            "maxLength": 2000
          }
        }
      },
      "ReindexProgressResponse": {
        "type": "object",
        "required": [
          "ok",
          "jobId",
          "message",
          "requestId"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "jobId": {
            "type": "string",
            "format": "uuid"
          },
          "message": {
            "type": "string"
          },
          "requestId": {
            "type": "string"
          }
        }
      },
      "ChatRequest": {
        "type": "object",
        "anyOf": [
          {
            "required": [
              "application"
            ]
          },
          {
            "required": [
              "project"
            ]
          },
          {
            "required": [
              "model"
            ]
          }
        ],
        "properties": {
          "application": {
            "type": "string",
            "description": "Application slug. Preferred field name.",
            "example": "resume-parser"
          },
          "project": {
            "type": "string",
            "description": "Legacy alias for `application`. Still supported.",
            "example": "resume-parser"
          },
          "model": {
            "type": "string",
            "description": "Accepted from OpenAI SDK clients as an alias for `application`. VERIS selects the model.",
            "example": "resume-parser"
          },
          "environment": {
            "type": "string",
            "default": "production",
            "example": "production"
          },
          "workload": {
            "type": "string",
            "example": "extract"
          },
          "task": {
            "type": "string"
          },
          "input": {
            "type": "string",
            "description": "Shorthand for a single user message.",
            "example": "Extract name, email, and years of experience from this resume."
          },
          "messages": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "role"
              ],
              "properties": {
                "role": {
                  "type": "string",
                  "enum": [
                    "system",
                    "user",
                    "assistant",
                    "tool"
                  ]
                },
                "content": {
                  "type": "string"
                }
              }
            }
          },
          "maxCostUsd": {
            "type": "number",
            "minimum": 0
          }
        }
      },
      "OpenAiChatRequest": {
        "type": "object",
        "required": [
          "model",
          "messages"
        ],
        "description": "Standard OpenAI chat completion body. Unsupported standard fields are rejected with a 400 naming the field.",
        "properties": {
          "model": {
            "type": "string",
            "description": "`veris-auto` lets VERIS choose. Any other value must name a real model. Never an application slug.",
            "example": "veris-auto"
          },
          "messages": {
            "type": "array",
            "description": "OpenAI messages. Content may be a string or an array of `text` / `image_url` parts. Tool turns round-trip: an assistant message may carry `tool_calls`, and a `tool` message must carry the matching `tool_call_id`. VERIS transports tool history and never executes a tool.",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "stream": {
            "type": "boolean",
            "description": "Stream OpenAI-shaped SSE chunks."
          },
          "tools": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "tool_choice": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "object",
                "additionalProperties": true
              }
            ]
          },
          "response_format": {
            "type": "object",
            "additionalProperties": true,
            "description": "`json_object` or `json_schema` structured output."
          },
          "temperature": {
            "type": "number"
          },
          "max_tokens": {
            "type": "integer"
          },
          "provider_options": {
            "type": "object",
            "additionalProperties": true,
            "description": "Provider-specific controls passed through to the selected provider."
          }
        }
      },
      "OpenAiChatResponse": {
        "type": "object",
        "required": [
          "id",
          "object",
          "created",
          "model",
          "choices"
        ],
        "properties": {
          "id": {
            "type": "string",
            "example": "chatcmpl-5f3a"
          },
          "object": {
            "type": "string",
            "enum": [
              "chat.completion"
            ]
          },
          "created": {
            "type": "integer"
          },
          "model": {
            "type": "string",
            "example": "gpt-4.1-nano"
          },
          "choices": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "index": {
                  "type": "integer"
                },
                "message": {
                  "type": "object",
                  "additionalProperties": true
                },
                "finish_reason": {
                  "type": "string",
                  "example": "stop"
                }
              }
            }
          },
          "usage": {
            "type": "object",
            "properties": {
              "prompt_tokens": {
                "type": "integer"
              },
              "completion_tokens": {
                "type": "integer"
              },
              "total_tokens": {
                "type": "integer"
              }
            }
          }
        }
      },
      "ChatResponse": {
        "type": "object",
        "required": [
          "requestId",
          "status",
          "provider",
          "model",
          "text"
        ],
        "properties": {
          "requestId": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "ok",
              "fallback"
            ]
          },
          "provider": {
            "type": "string",
            "example": "openai"
          },
          "model": {
            "type": "string",
            "example": "gpt-4o-mini"
          },
          "text": {
            "type": "string"
          },
          "inputTokens": {
            "type": "integer"
          },
          "outputTokens": {
            "type": "integer"
          },
          "latencyMs": {
            "type": "integer"
          },
          "costUsd": {
            "type": "number"
          },
          "fallbackUsed": {
            "type": "boolean"
          },
          "workload": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "EmbedRequest": {
        "type": "object",
        "required": [
          "input"
        ],
        "anyOf": [
          {
            "required": [
              "application"
            ]
          },
          {
            "required": [
              "project"
            ]
          }
        ],
        "properties": {
          "application": {
            "type": "string",
            "description": "Application slug. Preferred field name.",
            "example": "resume-parser"
          },
          "project": {
            "type": "string",
            "description": "Legacy alias for `application`. Still supported.",
            "example": "resume-parser"
          },
          "environment": {
            "type": "string",
            "default": "production",
            "example": "production"
          },
          "workload": {
            "type": "string"
          },
          "input": {
            "oneOf": [
              {
                "type": "string",
                "example": "Senior software engineer with 8 years of backend experience."
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "minItems": 1
              }
            ]
          },
          "model": {
            "type": "string",
            "description": "Optional caller-specified model."
          },
          "dimensions": {
            "type": "integer",
            "minimum": 1,
            "description": "Output vector length (only supported by some providers)."
          },
          "encoding_format": {
            "type": "string",
            "enum": [
              "float"
            ],
            "description": "Accepted for OpenAI parity. VERIS always returns float arrays."
          },
          "maxCostUsd": {
            "type": "number",
            "minimum": 0
          }
        }
      },
      "EmbedResponse": {
        "type": "object",
        "required": [
          "object",
          "data",
          "model",
          "usage"
        ],
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "list"
            ]
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "object": {
                  "type": "string",
                  "enum": [
                    "embedding"
                  ]
                },
                "index": {
                  "type": "integer"
                },
                "embedding": {
                  "type": "array",
                  "items": {
                    "type": "number"
                  }
                }
              }
            }
          },
          "model": {
            "type": "string"
          },
          "provider": {
            "type": "string"
          },
          "usage": {
            "type": "object",
            "properties": {
              "prompt_tokens": {
                "type": "integer"
              },
              "total_tokens": {
                "type": "integer"
              }
            }
          },
          "requestId": {
            "type": "string",
            "format": "uuid"
          },
          "dimensions": {
            "type": "integer"
          },
          "latencyMs": {
            "type": "integer"
          },
          "costUsd": {
            "type": "number"
          },
          "fallbackUsed": {
            "type": "boolean"
          }
        }
      }
    }
  }
}