{
  "openapi": "3.1.1",
  "info": {
    "title": "Enrichment API \u2014 Local Developer Preview",
    "version": "0.1.0",
    "summary": "Asynchronous enrichment contracts, developer keys, and sandbox accounting.",
    "description": "Local first milestone for a separate developer product. Default mode extracts supplied text completely but returns a partial job because semantic enrichment is unavailable. URL fetching requires an explicitly configured bridge. No paid credits, checkout, hosted service, or MCP transport is implemented. Console/session administration is intentionally separate from this public API."
  },
  "servers": [
    {
      "url": "http://127.0.0.1:4343",
      "description": "Local sandbox only"
    }
  ],
  "tags": [
    {
      "name": "Enrichments",
      "description": "Submit, retrieve, and delete enrichment jobs."
    },
    {
      "name": "Credits",
      "description": "Sandbox accounting; no money-moving operations."
    }
  ],
  "security": [
    {
      "DeveloperKey": []
    }
  ],
  "paths": {
    "/v1/enrichments": {
      "post": {
        "operationId": "createEnrichment",
        "tags": [
          "Enrichments"
        ],
        "summary": "Create an enrichment job",
        "description": "Accepts text or a public URL. Requires project-scoped idempotency. The default local engine returns partial text-only results and does not fetch URLs. Credits are local sandbox units only. Request bodies and input variants reject unknown fields. Required developer-key scope: enrichments:write. Requests must have Content-Type: application/json and a body no larger than 128 KiB. Shared mode uses the common enrichment engine for text and an explicitly configured source-reader endpoint for URLs. Inspect evidence coverage and capabilities; a completed job does not promise exhaustive enrichment.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateEnrichment"
              },
              "examples": {
                "text": {
                  "summary": "Extract supplied text",
                  "value": {
                    "input": {
                      "kind": "text",
                      "text": "The workshop takes place on 18 October. Bring a notebook."
                    },
                    "max_credits": 1
                  }
                },
                "url": {
                  "summary": "URL input: fails without charge in default sandbox",
                  "value": {
                    "input": {
                      "kind": "url",
                      "url": "https://example.com/article"
                    },
                    "max_credits": 1
                  }
                }
              }
            }
          }
        },
        "responses": {
          "400": {
            "description": "Invalid request, body, or required header.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked developer key.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "402": {
            "description": "Insufficient available sandbox credits.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "The credential does not authorize this operation.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "Idempotency key already used with a different normalized request.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "413": {
            "description": "Request body exceeds the supported size.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Request or concurrency limit exceeded.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              },
              "Retry-After": {
                "description": "Seconds before retrying.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "500": {
            "description": "Internal service failure.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "202": {
            "description": "New job admitted. One sandbox credit is reserved; poll the job URL for its terminal result.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              },
              "Location": {
                "description": "Relative URL for GET of the admitted job.",
                "schema": {
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Suggested number of seconds before polling.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                }
              }
            }
          },
          "200": {
            "description": "Idempotent replay. Returns the original job without another reservation, including a redacted deleted tombstone when applicable.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              },
              "Location": {
                "description": "Relative URL for GET of the admitted job.",
                "schema": {
                  "type": "string"
                }
              },
              "Retry-After": {
                "description": "Suggested number of seconds before polling.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                }
              }
            }
          },
          "415": {
            "description": "Unsupported media type. Submit Content-Type: application/json.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "x-required-scopes": [
          "enrichments:write"
        ]
      },
      "get": {
        "operationId": "listEnrichments",
        "tags": [
          "Enrichments"
        ],
        "summary": "List retained jobs",
        "description": "Returns visible jobs belonging to the authenticated project; excludes deleted and expired jobs. Pagination is a future production requirement. Required developer-key scope: enrichments:read.",
        "responses": {
          "200": {
            "description": "Project jobs.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobList"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked developer key.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "The credential does not authorize this operation.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Request or concurrency limit exceeded.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              },
              "Retry-After": {
                "description": "Seconds before retrying.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "500": {
            "description": "Internal service failure.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "x-required-scopes": [
          "enrichments:read"
        ]
      }
    },
    "/v1/enrichments/{id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/JobId"
        }
      ],
      "get": {
        "operationId": "getEnrichment",
        "tags": [
          "Enrichments"
        ],
        "summary": "Read an enrichment job",
        "description": "A failed job still returns HTTP 200 with its lifecycle status and error. A deleted, expired, or other-project job returns 404. Polling never creates a new charge. Required developer-key scope: enrichments:read.",
        "responses": {
          "200": {
            "description": "Owned job and any available result.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked developer key.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "The credential does not authorize this operation.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "No visible job with this ID belongs to this project.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Request or concurrency limit exceeded.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              },
              "Retry-After": {
                "description": "Seconds before retrying.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "500": {
            "description": "Internal service failure.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "x-required-scopes": [
          "enrichments:read"
        ]
      },
      "delete": {
        "operationId": "deleteEnrichment",
        "tags": [
          "Enrichments"
        ],
        "summary": "Delete a retained enrichment",
        "description": "Revokes access to source/result data and releases any unsettled reservation. Completed work is not refunded. Redacted accounting and idempotency tombstones remain. A late worker result must not restore the deleted data. Required developer-key scope: enrichments:write.",
        "responses": {
          "204": {
            "description": "Deletion accepted. There is no response body.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked developer key.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "The credential does not authorize this operation.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "No visible job with this ID belongs to this project.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Request or concurrency limit exceeded.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              },
              "Retry-After": {
                "description": "Seconds before retrying.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "500": {
            "description": "Internal service failure.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "x-required-scopes": [
          "enrichments:write"
        ]
      }
    },
    "/v1/balance": {
      "get": {
        "operationId": "getBalance",
        "tags": [
          "Credits"
        ],
        "summary": "Read sandbox credit balance",
        "description": "Sandbox units have no monetary value. Key creation and credit administration are not part of this public API. Required developer-key scope: usage:read.",
        "responses": {
          "200": {
            "description": "Project sandbox balance.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Balance"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked developer key.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "The credential does not authorize this operation.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Request or concurrency limit exceeded.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              },
              "Retry-After": {
                "description": "Seconds before retrying.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "500": {
            "description": "Internal service failure.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "x-required-scopes": [
          "usage:read"
        ]
      }
    },
    "/v1/usage": {
      "get": {
        "operationId": "getUsage",
        "tags": [
          "Credits"
        ],
        "summary": "Read the sandbox accounting ledger",
        "description": "Positive or negative deltas describe each balance change. Accounting entries remain after result deletion. No source text or credential secrets appear in ledger entries. Required developer-key scope: usage:read.",
        "responses": {
          "200": {
            "description": "Project ledger.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageList"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked developer key.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "The credential does not authorize this operation.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "description": "Request or concurrency limit exceeded.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              },
              "Retry-After": {
                "description": "Seconds before retrying.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "500": {
            "description": "Internal service failure.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "x-required-scopes": [
          "usage:read"
        ]
      }
    }
  },
  "components": {
    "securitySchemes": {
      "DeveloperKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "opaque developer key",
        "description": "Create a local key in the developer console. Send Authorization: Bearer <key>. Keys cannot administer the console and must not appear in URLs or MCP tool arguments."
      }
    },
    "parameters": {
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": true,
        "description": "Project-scoped operation identifier of 8-128 ASCII letters, digits, dots, colons, underscores or hyphens. Same normalized body replays the original job; a changed body returns 409. Stable across retries; use a new value for intentional new work.",
        "schema": {
          "type": "string",
          "minLength": 8,
          "maxLength": 128,
          "pattern": "^[A-Za-z0-9._:-]{8,128}$"
        }
      },
      "JobId": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Opaque enrichment job identifier.",
        "schema": {
          "type": "string"
        }
      }
    },
    "headers": {
      "RequestId": {
        "description": "Request trace identifier.",
        "schema": {
          "type": "string"
        }
      }
    },
    "schemas": {
      "TextInput": {
        "type": "object",
        "properties": {
          "kind": {
            "const": "text",
            "type": "string"
          },
          "text": {
            "type": "string",
            "minLength": 1,
            "description": "Text to enrich. It must contain a non-whitespace character and be at most 20,000 characters before trimming. Leading and trailing whitespace is normalized before hashing. The local sandbox returns only extracted supplied text; semantic enrichment is unavailable.",
            "maxLength": 20000,
            "pattern": "\\S"
          }
        },
        "required": [
          "kind",
          "text"
        ],
        "additionalProperties": false
      },
      "UrlInput": {
        "type": "object",
        "properties": {
          "kind": {
            "const": "url",
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Public HTTP(S) URL, at most 2,048 characters, with no embedded credentials, IP literals, custom ports, or internal/reserved hostname suffixes. The default sandbox does not fetch it; the admitted job fails without charge. Explicit bridge mode may read it with upstream reader protections.",
            "maxLength": 2048,
            "pattern": "^https?://"
          }
        },
        "required": [
          "kind",
          "url"
        ],
        "additionalProperties": false
      },
      "CreateEnrichment": {
        "type": "object",
        "properties": {
          "input": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/TextInput"
              },
              {
                "$ref": "#/components/schemas/UrlInput"
              }
            ],
            "discriminator": {
              "propertyName": "kind",
              "mapping": {
                "text": "#/components/schemas/TextInput",
                "url": "#/components/schemas/UrlInput"
              }
            }
          },
          "max_credits": {
            "type": "integer",
            "minimum": 1,
            "default": 1,
            "description": "Spend ceiling in sandbox units. The local milestone always reserves at most 1 unit, even when a larger ceiling is supplied.",
            "maximum": 1000000
          }
        },
        "required": [
          "input"
        ],
        "additionalProperties": false
      },
      "ErrorDetail": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "code",
          "message"
        ],
        "additionalProperties": false
      },
      "ApiError": {
        "type": "object",
        "properties": {
          "error": {
            "$ref": "#/components/schemas/ErrorDetail"
          },
          "request_id": {
            "type": "string",
            "description": "Request trace identifier; safe to share when troubleshooting."
          }
        },
        "required": [
          "error",
          "request_id"
        ],
        "additionalProperties": false
      },
      "JobInput": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "text",
              "url"
            ]
          },
          "name": {
            "type": "string"
          }
        },
        "required": [
          "kind"
        ],
        "additionalProperties": false
      },
      "JobUsage": {
        "type": "object",
        "properties": {
          "reserved_credits": {
            "type": "integer",
            "minimum": 0
          },
          "charged_credits": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "reserved_credits",
          "charged_credits"
        ],
        "additionalProperties": false
      },
      "Job": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "processing",
              "completed",
              "partial",
              "failed",
              "deleted"
            ],
            "description": "Lifecycle status. Inspect sources and capabilities independently for evidence coverage."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "Retention boundary, 24 hours after creation in this local milestone."
          },
          "input": {
            "$ref": "#/components/schemas/JobInput"
          },
          "result": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/EnrichmentResult"
              },
              {
                "type": "null"
              }
            ]
          },
          "error": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ErrorDetail"
              },
              {
                "type": "null"
              }
            ]
          },
          "usage": {
            "$ref": "#/components/schemas/JobUsage"
          }
        },
        "required": [
          "id",
          "status",
          "created_at",
          "updated_at",
          "expires_at",
          "input",
          "result",
          "error",
          "usage"
        ],
        "additionalProperties": false
      },
      "ObjectDescription": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          }
        },
        "required": [
          "kind",
          "title",
          "description"
        ],
        "additionalProperties": false
      },
      "Content": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string"
          },
          "markdown": {
            "type": "string",
            "description": "Optional normalized rich text from the shared engine."
          }
        },
        "required": [
          "text"
        ],
        "additionalProperties": false
      },
      "Fact": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "text": {
            "type": "string"
          },
          "origin": {
            "type": "string",
            "enum": [
              "extracted",
              "generated"
            ]
          },
          "citation_ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "id",
          "text",
          "origin",
          "citation_ids"
        ],
        "additionalProperties": false
      },
      "Source": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "kind": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "coverage": {
            "type": "string",
            "enum": [
              "full",
              "partial",
              "metadata",
              "none"
            ],
            "description": "Coverage of the source under the named methods, not a guarantee of correctness or universal understanding."
          },
          "methods": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "id",
          "kind",
          "coverage",
          "methods",
          "warnings"
        ],
        "additionalProperties": false
      },
      "Citation": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "source_id": {
            "type": "string"
          },
          "quote": {
            "type": "string"
          },
          "locator": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "source_id"
        ],
        "additionalProperties": false
      },
      "Capability": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "completed",
              "partial",
              "unavailable"
            ]
          },
          "method": {
            "type": "string"
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "name",
          "status",
          "method",
          "warnings"
        ],
        "additionalProperties": false
      },
      "EnrichmentResult": {
        "type": "object",
        "properties": {
          "schema_version": {
            "const": "1.0",
            "type": "string"
          },
          "object": {
            "$ref": "#/components/schemas/ObjectDescription"
          },
          "content": {
            "$ref": "#/components/schemas/Content"
          },
          "facts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Fact"
            }
          },
          "entities": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Entity"
            },
            "description": "Normalized entities from shared-engine output. The default sandbox and legacy compatibility bridge return an empty array."
          },
          "sources": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Source"
            }
          },
          "citations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Citation"
            }
          },
          "capabilities": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Capability"
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "extensions": {
            "type": "object",
            "properties": {
              "gisted": {
                "type": "object",
                "additionalProperties": true,
                "description": "Optional Gisted compatibility output from the explicitly configured bridge; not the neutral result contract."
              }
            },
            "additionalProperties": true
          }
        },
        "required": [
          "schema_version",
          "object",
          "content",
          "facts",
          "entities",
          "sources",
          "citations",
          "capabilities",
          "warnings"
        ],
        "additionalProperties": false
      },
      "JobList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Job"
            }
          }
        },
        "required": [
          "data"
        ],
        "additionalProperties": false
      },
      "Balance": {
        "type": "object",
        "properties": {
          "available": {
            "type": "integer",
            "minimum": 0
          },
          "reserved": {
            "type": "integer",
            "minimum": 0
          },
          "spent": {
            "type": "integer",
            "minimum": 0
          },
          "unit": {
            "type": "string",
            "const": "sandbox_credit"
          }
        },
        "required": [
          "available",
          "reserved",
          "spent",
          "unit"
        ],
        "additionalProperties": false
      },
      "LedgerEntry": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "job_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "type": {
            "type": "string",
            "enum": [
              "grant",
              "reserve",
              "charge",
              "release"
            ]
          },
          "available_delta": {
            "type": "integer"
          },
          "reserved_delta": {
            "type": "integer"
          },
          "spent_delta": {
            "type": "integer"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "job_id",
          "type",
          "available_delta",
          "reserved_delta",
          "spent_delta",
          "created_at"
        ],
        "additionalProperties": false
      },
      "UsageList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LedgerEntry"
            }
          }
        },
        "required": [
          "data"
        ],
        "additionalProperties": false
      },
      "Entity": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "kind": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "citation_ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "id",
          "name",
          "kind",
          "citation_ids"
        ],
        "additionalProperties": false,
        "description": "An entity identified by the shared engine. Citation IDs refer to result citations; an empty list means no direct source quote was verified."
      }
    }
  }
}
