OpenAPI 3.1.0
AI Code Review Server API
Version 1.0.0
Canonical API for submitting PHP and Drupal code reviews. Each review executes through a provider profile the calling site registered on the administrator-only control plane; a request never carries a provider credential, upstream, header, route, or raw model identifier.
Operations
| Method | Path | Operation | Summary | Authentication | Request | Parameters | Responses |
|---|---|---|---|---|---|---|---|
GET | /healthz | getLiveness | Check whether the Drupal request path is alive | None | None | None |
|
GET | /readyz | getReadiness | Check configured review traffic and enabled language sidecar readiness | None | None | None |
|
POST | /api/ai-code-review/v1/reviews | createReview | Submit a repository change for review | bearerAuth | application/json (required ReviewRequest) | header:X-Request-ID, header:Idempotency-Key, header:Prefer |
|
GET | /api/ai-code-review/v1/reviews/{reviewId} | getReviewStatus | Retrieve owner-scoped review lifecycle status | bearerAuth | None | header:X-Request-ID, path:reviewId |
|
DELETE | /api/ai-code-review/v1/reviews/{reviewId} | cancelReview | Cancel an owner-scoped queued or running review | bearerAuth | None | header:X-Request-ID, path:reviewId |
|
GET | /api/ai-code-review/v1/reviews/{reviewId}/result | getReviewResult | Retrieve the structured result of a completed owner-scoped review | bearerAuth | None | header:X-Request-ID, path:reviewId |
|
GET | /api/ai-code-review/v1/provider-profile-capabilities | getProviderProfileCapabilities | Discover provider-profile registration capabilities | bearerAuth | None | header:X-Request-ID |
|
POST | /api/ai-code-review/v1/provider-profiles | createProviderProfile | Register a provider profile, delivering its credential once | bearerAuth | application/json (required ProviderProfileRegistration) | header:X-Request-ID |
|
GET | /api/ai-code-review/v1/provider-profiles | listProviderProfiles | List the caller's provider profiles | bearerAuth | None | header:X-Request-ID |
|
GET | /api/ai-code-review/v1/provider-profiles/{profileId} | getProviderProfile | Read one caller-owned provider profile | bearerAuth | None | header:X-Request-ID, path:profileId |
|
DELETE | /api/ai-code-review/v1/provider-profiles/{profileId} | revokeProviderProfile | Revoke one caller-owned provider profile | bearerAuth | None | header:X-Request-ID, path:profileId |
|
POST | /api/ai-code-review/v1/provider-profiles/{profileId}/rotate | rotateProviderProfile | Replace a profile's credential and advance its version | bearerAuth | application/json (required ProviderProfileRotation) | header:X-Request-ID, path:profileId |
|
Components
Headers
AuthenticationChallenge
{
"description": "Service-token authentication challenge",
"schema": {
"type": "string",
"const": "Bearer realm=\"AI Code Review Server\""
}
}RequestId
{
"description": "Server-accepted or server-generated request identifier",
"schema": {
"type": "string"
}
}RetryAfter
{
"description": "Seconds before the client should retry request admission",
"schema": {
"type": "integer",
"minimum": 1
}
}Parameters
RequestId
{
"name": "X-Request-ID",
"in": "header",
"required": false,
"description": "Optional caller correlation identifier. Values containing 1 to 128 characters from A-Z, a-z, 0-9, dot, underscore, colon, and hyphen are retained. Other values are replaced with a server-generated identifier.",
"schema": {
"type": "string"
},
"x-retained-value-schema": {
"type": "string",
"minLength": 1,
"maxLength": 128,
"pattern": "^[A-Za-z0-9._:-]+$"
}
}IdempotencyKey
{
"name": "Idempotency-Key",
"in": "header",
"required": false,
"description": "Opaque key for safely retrying one review submission",
"schema": {
"type": "string",
"minLength": 16,
"maxLength": 128,
"pattern": "^[A-Za-z0-9._:-]+$"
}
}Prefer
{
"name": "Prefer",
"in": "header",
"required": false,
"description": "Set to respond-async to request asynchronous processing",
"schema": {
"type": "string",
"enum": [
"respond-async"
]
}
}ProfileId
{
"name": "profileId",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}Responses
BadRequest
{
"description": "Malformed framing, malformed JSON, or duplicate properties within structural limits",
"headers": {
"X-Request-ID": {
"$ref": "#/components/headers/RequestId"
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}Unauthorized
{
"description": "Missing or invalid service authentication",
"headers": {
"WWW-Authenticate": {
"$ref": "#/components/headers/AuthenticationChallenge"
},
"X-Request-ID": {
"$ref": "#/components/headers/RequestId"
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}Forbidden
{
"description": "Authenticated caller is not allowed to perform this review",
"headers": {
"X-Request-ID": {
"$ref": "#/components/headers/RequestId"
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}MethodNotAllowed
{
"description": "The request method is not supported by this endpoint",
"headers": {
"Allow": {
"description": "Methods supported by this endpoint",
"schema": {
"type": "string"
}
},
"X-Request-ID": {
"$ref": "#/components/headers/RequestId"
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}NotAcceptable
{
"description": "The requested response representation is not available",
"headers": {
"X-Request-ID": {
"$ref": "#/components/headers/RequestId"
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}Conflict
{
"description": "Idempotency conflict or incompatible repository state",
"headers": {
"X-Request-ID": {
"$ref": "#/components/headers/RequestId"
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}ContentTooLarge
{
"description": "Request, repository, or diff exceeds a limit evaluated before duplicate detection",
"headers": {
"X-Request-ID": {
"$ref": "#/components/headers/RequestId"
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}UnsupportedMediaType
{
"description": "The request content type or content encoding is not supported",
"headers": {
"X-Request-ID": {
"$ref": "#/components/headers/RequestId"
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}UnprocessableContent
{
"description": "Depth, request fields, or Git references fail validation",
"headers": {
"X-Request-ID": {
"$ref": "#/components/headers/RequestId"
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}TooManyRequests
{
"description": "Per-client rate or concurrency limit, or asynchronous review backlog capacity, was exceeded",
"headers": {
"Retry-After": {
"$ref": "#/components/headers/RetryAfter"
},
"X-Request-ID": {
"$ref": "#/components/headers/RequestId"
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}InternalError
{
"description": "Unexpected internal failure",
"headers": {
"X-Request-ID": {
"$ref": "#/components/headers/RequestId"
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}BadGateway
{
"description": "APISIX or an LLM provider returned an invalid response, or an enabled private language analyzer returned malformed output or failed its tool. No analyzer path, source, tool output, or private sidecar outcome is returned.",
"headers": {
"X-Request-ID": {
"$ref": "#/components/headers/RequestId"
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}Unavailable
{
"description": "Review service or a required dependency is unavailable, including an enabled language analyzer whose compatible sidecar is not ready. Disabled review submission uses the canonical service_unavailable code after authentication and route permission, without accepting work.",
"headers": {
"Retry-After": {
"$ref": "#/components/headers/RetryAfter"
},
"X-Request-ID": {
"$ref": "#/components/headers/RequestId"
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}ProviderProfileNotFound
{
"description": "The profile does not exist or is not owned by the caller",
"headers": {
"X-Request-ID": {
"$ref": "#/components/headers/RequestId"
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}ProvisionerUnavailable
{
"description": "The APISIX credential provisioner is unavailable (error code provider_provisioner_unavailable). New managed creates require a durable, versioned idempotency client; an interface-only provisioner is refused before the credential envelope is opened or a capacity slot is reserved. A failure after a remote attempt is ambiguous: an identified create or rotation has reserved its durable operation, and a managed rotation may already have advanced the profile and queued its superseded route for removal. Reconcile by replaying the same registration_id, or the same rotation_id and expected_version, rather than starting a new logical operation. An attempted request without an identifier is reconciled by the server's own maintenance.",
"headers": {
"X-Request-ID": {
"$ref": "#/components/headers/RequestId"
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}ProviderProfileRegistrationUnavailable
{
"description": "The registration key material is unavailable or unusable",
"headers": {
"X-Request-ID": {
"$ref": "#/components/headers/RequestId"
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}GatewayTimeout
{
"description": "Review, private language analyzer, or backend LLM processing exceeded its deadline.",
"headers": {
"Retry-After": {
"$ref": "#/components/headers/RetryAfter"
},
"X-Request-ID": {
"$ref": "#/components/headers/RequestId"
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}Security schemes
bearerAuth
{
"type": "http",
"scheme": "bearer",
"bearerFormat": "<client-id>.<secret>",
"description": "Deployment-owned client-to-server service token. This is not an APISIX or LLM provider credential. The lowercase client ID starts with an ASCII letter and then contains only letters, digits, underscores, or hyphens."
}Schemas
HealthStatus
{
"type": "object",
"additionalProperties": false,
"required": [
"status"
],
"properties": {
"status": {
"type": "string",
"enum": [
"ok",
"ready",
"not_ready"
]
}
}
}ReviewRequest
{
"type": "object",
"additionalProperties": false,
"required": [
"repository_url",
"branch",
"base_commit_id",
"commit_id",
"provider_profile_id"
],
"properties": {
"repository_url": {
"type": "string",
"format": "uri",
"maxLength": 2048,
"pattern": "^[Hh][Tt][Tt][Pp][Ss]://(?:\\[[0-9A-Fa-f:.]+\\]|\\[[Vv][0-9A-Fa-f]+\\.[A-Za-z0-9._~!$&'()*+,;=:-]+\\]|(?:[A-Za-z0-9._~!$&'()*+,;=-]|%[0-9A-Fa-f]{2})+)(?::(?:[0-9]{1,4}|[0-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]))?(?:/(?:[A-Za-z0-9._~!$&'()*+,;=:@-]|%[0-9A-Fa-f]{2})*)*(?:\\?(?:[A-Za-z0-9._~!$&'()*+,;=:@/?-]|%[0-9A-Fa-f]{2})*)?(?:#(?:[A-Za-z0-9._~!$&'()*+,;=:@/?-]|%[0-9A-Fa-f]{2})*)?(?![\\s\\S])",
"description": "HTTPS URL with an optional port from 0 through 65535"
},
"branch": {
"type": "string",
"minLength": 1,
"maxLength": 255,
"pattern": "^(?!HEAD(?![\\s\\S]))(?![-/])(?!\\.)(?![\\s\\S]*/\\.)(?![^/]*\\.lock(?:/|(?![\\s\\S])))(?![\\s\\S]*/[^/]*\\.lock(?:/|(?![\\s\\S])))(?![\\s\\S]*(?://|\\.\\.|@\\{|[\\x00-\\x20\\x7F~^:?*\\[\\\\]))(?![\\s\\S]*[/.](?![\\s\\S]))[\\s\\S]+$"
},
"base_commit_id": {
"$ref": "#/components/schemas/CanonicalGitObjectId"
},
"commit_id": {
"$ref": "#/components/schemas/CanonicalGitObjectId"
},
"output_language": {
"type": "string",
"minLength": 2,
"maxLength": 35,
"pattern": "^[A-Za-z]{2,8}(-[A-Za-z0-9]{1,8})*(?![\\s\\S])",
"description": "Uses the deployment-configured default when omitted."
},
"review_policy": {
"$ref": "#/components/schemas/ReviewPolicy"
},
"environments": {
"description": "Caller-provided target environments rendered verbatim on one line in every chunk. Reject C0/C1 controls, TAB, CR, LF, NEL, U+2028, U+2029, bidi controls, Unicode tags, and consecutive variation selectors. No policy permission is required for environments alone.",
"type": "array",
"maxItems": 20,
"uniqueItems": true,
"items": {
"type": "string",
"minLength": 1,
"maxLength": 120
}
},
"provider_profile_id": {
"$ref": "#/components/schemas/ProviderProfileId"
}
}
}ReviewPolicy
{
"type": "object",
"additionalProperties": false,
"required": [
"format",
"content"
],
"description": "Optional caller criteria, never server instructions. Explicit null is invalid. Structural and fixed validation precede owner/key digest replay; new policy submissions then require submit ai code review policies permission (403 access_denied), followed by the operational byte cap (422). Accepted identical replays survive permission revocation and operational-cap reduction; changed criteria return 409.",
"properties": {
"format": {
"type": "string",
"enum": [
"text/markdown",
"text/plain"
]
},
"content": {
"type": "string",
"minLength": 1,
"maxLength": 98307,
"x-canonical-maximum-utf8-bytes": 49152,
"x-default-submission-maximum-utf8-bytes": 32768,
"description": "UTF-8 text. Convert CRLF and CR to LF and remove exactly one leading BOM before validation, hashing and storage; otherwise preserve bytes. Canonical content must be nonempty and at most 49152 UTF-8 bytes; new submissions default to a configurable 32768-byte cap. The larger wire maxLength accommodates CRLF and BOM before canonicalization; the independent HTTP JSON document ceiling is 1048576 bytes. Reject C0/C1 controls except TAB/LF, bidi controls, Unicode tags, and consecutive variation selectors. Include the full canonical document in every chunk. Source criteria from trusted base/config independent of the reviewed head; the server cannot prove provenance."
}
}
}ReviewPolicyReceipt
{
"type": "object",
"additionalProperties": false,
"required": [
"format",
"sha256",
"bytes"
],
"description": "Present if and only if the submission contained review_policy, including accepted replay after terminal input purge. Confirms canonical receipt, not model compliance. Absent for no-policy and environments-only requests.",
"properties": {
"format": {
"type": "string",
"enum": [
"text/markdown",
"text/plain"
]
},
"sha256": {
"type": "string",
"pattern": "^[0-9a-f]{64}$"
},
"bytes": {
"type": "integer",
"minimum": 1,
"maximum": 49152
}
}
}ProviderProfileId
{
"type": "string",
"format": "uuid",
"minLength": 36,
"maxLength": 36,
"pattern": "^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}(?![\\s\\S])",
"description": "Identifier of a provider profile registered by the calling client. For a new submission, an unknown, revoked, or foreign identifier is rejected with one identical validation error before repository checkout, queue allocation, or LLM request. An identical accepted owner/key replay returns its original review even after profile rotation or revocation; changed canonical input under that key conflicts. The accepted version is pinned to the review: a profile rotated or revoked before the worker runs fails that review with provider_profile_unavailable instead of executing with inputs the caller never saw."
}ProviderProfileRegistration
{
"type": "object",
"additionalProperties": false,
"description": "The create request body. It alone accepts registration_id; the rotate endpoint rejects that member as unknown and accepts rotation_id with expected_version instead.",
"required": [
"provider",
"model",
"execution_route",
"sealed_credential"
],
"properties": {
"provider": {
"type": "string",
"enum": [
"openai",
"azure_openai",
"anthropic"
],
"description": "Server allow-listed provider adapter. Only openai has a reviewed adapter today; the others are refused at registration."
},
"model": {
"type": "string",
"minLength": 1,
"maxLength": 128,
"description": "Provider model identifier, validated by the adapter."
},
"execution_route": {
"type": "string",
"enum": [
"apisix_managed",
"direct_server"
]
},
"sealed_credential": {
"type": "string",
"writeOnly": true,
"minLength": 1,
"maxLength": 8192,
"pattern": "^[A-Za-z0-9_-]+(?![\\s\\S])",
"description": "One-time base64url envelope: a JSON object with members v (1), kid (registration key identifier), and sealed (a libsodium sealed box, base64url) whose plaintext is a JSON object with members client_id (the caller's service-token client ID), issued_at (Unix seconds), nonce (base64url, 16-64 bytes), and credential (the provider API key). It is never returned, logged, or retained; a replayed nonce is refused."
},
"registration_id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}(?![\\s\\S])",
"description": "Optional, non-secret lowercase canonical UUID generated once by the client for one logical create. Supplying it makes a retry of that create converge on one profile identifier, one stored credential, and one APISIX route; the completed replay returns the existing profile with 201 without opening the newly supplied envelope. Reusing it with a different provider, model, or route returns provider_profile_registration_conflict, and a replay after revocation returns provider_profile_registration_revoked. A create without this member remains accepted and is treated as a new logical create."
}
}
}ProviderProfileRotation
{
"type": "object",
"additionalProperties": false,
"description": "The rotate request body. It carries the same four registration members and, unlike create, accepts rotation_id and expected_version. The create member registration_id is rejected here as unknown before the sealed envelope is opened.",
"required": [
"provider",
"model",
"execution_route",
"sealed_credential"
],
"properties": {
"provider": {
"$ref": "#/components/schemas/ProviderProfileRegistration/properties/provider"
},
"model": {
"$ref": "#/components/schemas/ProviderProfileRegistration/properties/model"
},
"execution_route": {
"$ref": "#/components/schemas/ProviderProfileRegistration/properties/execution_route"
},
"sealed_credential": {
"$ref": "#/components/schemas/ProviderProfileRegistration/properties/sealed_credential"
},
"rotation_id": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}(?![\\s\\S])",
"description": "Optional, non-secret lowercase canonical UUID identifying one logical rotation. It must be sent together with expected_version; one member alone is rejected with 422. A retry that repeats both reuses the reserved target version, so a managed rotation cannot materialize two routes."
},
"expected_version": {
"type": "integer",
"minimum": 1,
"description": "The active profile version the client rotated from. It must be sent together with rotation_id. A value that does not match the active version returns provider_profile_registration_conflict before the sealed envelope is opened."
}
}
}ProviderProfile
{
"type": "object",
"additionalProperties": false,
"required": [
"id",
"provider",
"model",
"execution_route",
"status",
"version",
"created_at",
"updated_at"
],
"properties": {
"id": {
"$ref": "#/components/schemas/ProviderProfileId"
},
"provider": {
"type": "string"
},
"model": {
"type": "string"
},
"execution_route": {
"type": "string",
"enum": [
"apisix_managed",
"direct_server"
]
},
"status": {
"type": "string",
"enum": [
"active",
"revoked"
]
},
"version": {
"type": "integer",
"minimum": 1
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
}
}ProviderProfileCollection
{
"type": "object",
"additionalProperties": false,
"required": [
"profiles"
],
"properties": {
"profiles": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ProviderProfile"
}
}
}
}ProviderProfileCapabilities
{
"type": "object",
"additionalProperties": false,
"required": [
"registration",
"providers"
],
"properties": {
"registration": {
"$ref": "#/components/schemas/ProviderProfileRegistrationCapabilities"
},
"providers": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ProviderProfileCapability"
}
}
}
}ProviderProfileRegistrationCapabilities
{
"type": "object",
"additionalProperties": false,
"required": [
"envelope_version",
"algorithm",
"key_id",
"public_key",
"maximum_envelope_age_seconds"
],
"properties": {
"envelope_version": {
"type": "integer",
"const": 1
},
"algorithm": {
"type": "string",
"const": "sodium_crypto_box_seal"
},
"key_id": {
"type": "string",
"minLength": 1,
"maxLength": 64,
"pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,63}(?![\\s\\S])"
},
"public_key": {
"type": "string",
"minLength": 43,
"maxLength": 43,
"pattern": "^[A-Za-z0-9_-]{43}(?![\\s\\S])",
"description": "Exactly 32 raw public-key bytes in unpadded base64url."
},
"maximum_envelope_age_seconds": {
"type": "integer",
"minimum": 1
}
}
}ProviderProfileCapability
{
"type": "object",
"additionalProperties": false,
"required": [
"id",
"execution_routes"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"maxLength": 64,
"pattern": "^[a-z][a-z0-9_]*(?![\\s\\S])"
},
"execution_routes": {
"type": "array",
"minItems": 1,
"uniqueItems": true,
"items": {
"type": "string",
"enum": [
"apisix_managed",
"direct_server"
]
}
}
}
}CanonicalGitObjectId
{
"type": "string",
"description": "Strict full SHA-1 or SHA-256 Git object identifier",
"pattern": "^(?:[0-9a-fA-F]{40}|[0-9a-fA-F]{64})(?![\\s\\S])"
}ReviewJob
{
"type": "object",
"additionalProperties": false,
"required": [
"review_id",
"result_url",
"status",
"status_url",
"submitted_at"
],
"properties": {
"review_policy": {
"$ref": "#/components/schemas/ReviewPolicyReceipt"
},
"review_id": {
"type": "string",
"format": "uuid"
},
"status": {
"type": "string",
"description": "Fixed v1 asynchronous-submission acceptance state.",
"const": "queued"
},
"status_url": {
"type": "string",
"format": "uri-reference"
},
"result_url": {
"type": "string",
"format": "uri-reference"
},
"submitted_at": {
"type": "string",
"format": "date-time"
},
"expires_at": {
"type": "string",
"format": "date-time"
}
}
}ReviewResult
{
"type": "object",
"additionalProperties": false,
"required": [
"review_id",
"status",
"findings",
"summary",
"rendered_result",
"completed_at"
],
"properties": {
"review_id": {
"type": "string",
"format": "uuid"
},
"status": {
"type": "string",
"const": "completed"
},
"findings": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Finding"
}
},
"summary": {
"$ref": "#/components/schemas/ReviewSummary"
},
"rendered_result": {
"type": "string",
"description": "Bounded plain-text report with Summary and Detail and dynamically sized backtick code fences; no ANSI escapes or HTML rendering"
},
"completed_at": {
"type": "string",
"format": "date-time"
}
}
}ReviewStatus
{
"type": "object",
"additionalProperties": false,
"required": [
"attempt",
"created_at",
"error_code",
"expires_at",
"finished_at",
"review_id",
"started_at",
"status"
],
"properties": {
"attempt": {
"type": "integer",
"minimum": 0
},
"created_at": {
"type": "string",
"format": "date-time"
},
"error_code": {
"type": [
"string",
"null"
]
},
"expires_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"finished_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"review_id": {
"type": "string",
"format": "uuid"
},
"started_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"status": {
"type": "string",
"enum": [
"cancelled",
"completed",
"expired",
"failed",
"queued",
"running"
]
}
}
}Finding
{
"type": "object",
"additionalProperties": false,
"description": "Actionable LLM feedback only; analyzer records remain review context and are not returned as findings",
"required": [
"finding_id",
"severity",
"category",
"message",
"path",
"line",
"suggestion",
"suggestion_format"
],
"properties": {
"finding_id": {
"type": "string",
"minLength": 1,
"maxLength": 128
},
"severity": {
"type": "string",
"enum": [
"critical",
"high",
"medium",
"low",
"info"
]
},
"category": {
"type": "string",
"minLength": 1,
"maxLength": 80
},
"message": {
"type": "string",
"minLength": 1,
"maxLength": 4000
},
"path": {
"type": "string",
"minLength": 1,
"maxLength": 1024
},
"line": {
"type": "integer",
"minimum": 1
},
"end_line": {
"type": [
"integer",
"null"
],
"minimum": 1
},
"function": {
"type": [
"string",
"null"
],
"minLength": 1,
"maxLength": 256,
"description": "Named function or method supported by supplied context; null when unavailable"
},
"suggestion": {
"type": "string",
"minLength": 1,
"maxLength": 8000,
"description": "Nonblank concrete corrected code or unified diff; never applied automatically"
},
"suggestion_format": {
"type": "string",
"enum": [
"code",
"unified_diff"
]
}
}
}ReviewSummary
{
"type": "object",
"additionalProperties": false,
"required": [
"files_reviewed",
"finding_count"
],
"properties": {
"files_reviewed": {
"type": "integer",
"minimum": 0
},
"finding_count": {
"type": "integer",
"minimum": 0
},
"truncated": {
"type": "boolean",
"default": false,
"description": "True when review material, findings, or rendered report bytes were omitted"
}
}
}ErrorResponse
{
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message",
"request_id"
],
"properties": {
"code": {
"type": "string",
"pattern": "^[a-z][a-z0-9_]*$"
},
"message": {
"type": "string",
"description": "Localized human-readable message; clients must use code for program logic. An oversized translation falls back to the bounded English source message.",
"minLength": 1,
"maxLength": 1000
},
"request_id": {
"type": "string"
},
"details": {
"type": "array",
"maxItems": 100,
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"path",
"code",
"message"
],
"properties": {
"path": {
"type": "string",
"description": "JSON Pointer to the invalid request value"
},
"code": {
"type": "string"
},
"message": {
"type": "string",
"description": "Localized human-readable validation message"
}
}
}
}
}
}
}
}