{
  "openapi": "3.1.0",
  "info": {
    "title": "OriginChain HTTP API",
    "summary": "The AI-native database — SQL, vector, full-text, graph, and natural-language queries against one managed single-tenant store.",
    "description": "OriginChain is a managed single-tenant AI-native database. Every write commits the row, its secondary indexes, its FTS postings, its vector embedding, and its relation edges on one WAL frame. This OpenAPI spec is auto-published at https://originchain.ai/openapi.json — copy it into your favourite SDK generator or feed it to an AI coding agent.\n\nGet a tenant + bearer at https://originchain.ai/docs/quickstart.",
    "version": "1.0.0",
    "contact": {
      "name": "OriginChain support",
      "url": "https://originchain.ai/contact",
      "email": "support@originchain.ai"
    },
    "license": {
      "name": "Apache-2.0",
      "url": "https://www.apache.org/licenses/LICENSE-2.0"
    }
  },
  "externalDocs": {
    "description": "OriginChain documentation",
    "url": "https://originchain.ai/docs"
  },
  "servers": [
    {
      "url": "https://{tenant_subdomain}.api.originchain.ai",
      "description": "Tenant-scoped HTTPS endpoint (one DNS per single-tenant instance).",
      "variables": {
        "tenant_subdomain": {
          "default": "your-tenant-id",
          "description": "Replace with the tenant subdomain provided when you provisioned the instance."
        }
      }
    }
  ],
  "security": [{ "bearerAuth": [] }],
  "tags": [
    { "name": "Schemas", "description": "Register and list table manifests." },
    { "name": "Rows", "description": "Insert and read individual rows." },
    { "name": "Query", "description": "Plan-tree query execution." },
    { "name": "SQL", "description": "Typed SQL with JOINs, aggregates, and CTEs." },
    { "name": "Ask", "description": "Natural-language query compiler." },
    { "name": "Vector", "description": "HNSW vector similarity search." },
    { "name": "FTS", "description": "BM25 full-text search." },
    { "name": "Graph", "description": "Relation traversal: BFS, Dijkstra, reverse." },
    { "name": "Migrations", "description": "Online schema migrations." },
    { "name": "Health", "description": "Liveness, readiness, metrics." }
  ],
  "paths": {
    "/health": {
      "get": {
        "tags": ["Health"],
        "summary": "Liveness probe (no auth).",
        "security": [],
        "responses": { "200": { "description": "OK" } }
      }
    },
    "/ready": {
      "get": {
        "tags": ["Health"],
        "summary": "Readiness probe (no auth).",
        "security": [],
        "responses": { "200": { "description": "Ready" }, "503": { "description": "Not ready" } }
      }
    },
    "/v1/tenants/{tenant}/schemas": {
      "parameters": [{ "$ref": "#/components/parameters/Tenant" }],
      "get": {
        "tags": ["Schemas"],
        "summary": "List registered schemas",
        "responses": {
          "200": {
            "description": "Array of schema IDs (\"namespace.table\").",
            "content": { "application/json": { "schema": { "type": "array", "items": { "type": "string" } } } }
          }
        }
      },
      "post": {
        "tags": ["Schemas"],
        "summary": "Register a new schema (TOML manifest)",
        "requestBody": {
          "required": true,
          "content": {
            "text/plain": {
              "schema": { "type": "string", "description": "TOML manifest body" },
              "example": "namespace = \"trading\"\ntable = \"orders\"\nprimary_key = [\"order_id\"]\n\n[[columns]]\nname = \"order_id\"\nty = \"str\"\nrequired = true\n"
            }
          }
        },
        "responses": {
          "200": { "description": "Registered.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SchemaRegisterResponse" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" }
        }
      },
      "delete": {
        "tags": ["Schemas"],
        "summary": "Delete every registered schema (operator-only)",
        "responses": {
          "200": {
            "description": "Deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": { "deleted": { "type": "integer" }, "ids": { "type": "array", "items": { "type": "string" } } }
                }
              }
            }
          }
        }
      }
    },
    "/v1/tenants/{tenant}/schemas/{id}": {
      "parameters": [
        { "$ref": "#/components/parameters/Tenant" },
        { "name": "id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Schema ID (namespace.table)." }
      ],
      "get": {
        "tags": ["Schemas"],
        "summary": "Fetch a schema manifest",
        "responses": {
          "200": { "description": "TOML body of the registered manifest.", "content": { "text/plain": { "schema": { "type": "string" } } } },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      },
      "delete": {
        "tags": ["Schemas"],
        "summary": "Delete a single schema",
        "responses": {
          "204": { "description": "Deleted." },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/v1/tenants/{tenant}/rows/{schema}": {
      "parameters": [
        { "$ref": "#/components/parameters/Tenant" },
        { "name": "schema", "in": "path", "required": true, "schema": { "type": "string" } }
      ],
      "post": {
        "tags": ["Rows"],
        "summary": "Insert a row",
        "description": "Atomically writes the row, its secondary indexes, its FTS postings (if any), its vector embedding (if the manifest declares one), and its graph edges on a single WAL frame.",
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true } } }
        },
        "responses": { "200": { "description": "Inserted." } }
      }
    },
    "/v1/tenants/{tenant}/rows/{schema}/{pk}": {
      "parameters": [
        { "$ref": "#/components/parameters/Tenant" },
        { "name": "schema", "in": "path", "required": true, "schema": { "type": "string" } },
        { "name": "pk", "in": "path", "required": true, "schema": { "type": "string" } }
      ],
      "get": {
        "tags": ["Rows"],
        "summary": "Read a row by primary key",
        "responses": {
          "200": { "description": "The row.", "content": { "application/json": { "schema": { "type": "object" } } } },
          "404": { "$ref": "#/components/responses/NotFound" }
        }
      }
    },
    "/v1/tenants/{tenant}/query": {
      "parameters": [{ "$ref": "#/components/parameters/Tenant" }],
      "post": {
        "tags": ["Query"],
        "summary": "Execute a plan tree",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "type": "object", "additionalProperties": true },
              "example": { "op": "scan", "schema": "trading.orders" }
            }
          }
        },
        "responses": { "200": { "description": "Result rows.", "content": { "application/json": { "schema": { "type": "array", "items": { "type": "object" } } } } } }
      }
    },
    "/v1/tenants/{tenant}/sql": {
      "parameters": [{ "$ref": "#/components/parameters/Tenant" }],
      "post": {
        "tags": ["SQL"],
        "summary": "Run a typed SQL statement",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "type": "object", "properties": { "sql": { "type": "string" } }, "required": ["sql"] },
              "example": { "sql": "SELECT symbol, COUNT(*) FROM trading.orders GROUP BY symbol" }
            }
          }
        },
        "responses": { "200": { "description": "Result rows.", "content": { "application/json": { "schema": { "type": "array", "items": { "type": "object" } } } } } }
      }
    },
    "/v1/tenants/{tenant}/ask": {
      "parameters": [{ "$ref": "#/components/parameters/Tenant" }],
      "post": {
        "tags": ["Ask"],
        "summary": "Natural-language query",
        "description": "Compiles English to a query plan once (cached), reuses the cached plan thereafter. First call may invoke an LLM; subsequent identical-shape asks return from cache in milliseconds.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "nl": { "type": "string", "description": "The English question." },
                  "plan_only": { "type": "boolean", "default": false, "description": "Return the compiled plan without executing." }
                },
                "required": ["nl"]
              },
              "example": { "nl": "trading.orders where symbol='AAPL'" }
            }
          }
        },
        "responses": { "200": { "description": "Plan + rows.", "content": { "application/json": { "schema": { "type": "object", "properties": { "plan": { "type": "object" }, "rows": { "type": "array", "items": { "type": "object" } } } } } } } }
      }
    },
    "/v1/tenants/{tenant}/watch": {
      "parameters": [{ "$ref": "#/components/parameters/Tenant" }],
      "get": {
        "tags": ["Query"],
        "summary": "Open an SSE stream that pushes deltas matching a saved query",
        "parameters": [
          { "name": "nl", "in": "query", "required": true, "schema": { "type": "string" }, "description": "Natural-language query whose result set you want to subscribe to." }
        ],
        "responses": { "200": { "description": "Server-sent events.", "content": { "text/event-stream": { "schema": { "type": "string" } } } } }
      }
    },
    "/v1/tenants/{tenant}/vector/{table}/put": {
      "parameters": [
        { "$ref": "#/components/parameters/Tenant" },
        { "name": "table", "in": "path", "required": true, "schema": { "type": "string" } }
      ],
      "post": {
        "tags": ["Vector"],
        "summary": "Upsert an embedding",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": { "type": "string" },
                  "embedding": { "type": "array", "items": { "type": "number" } },
                  "metadata": { "type": "object", "additionalProperties": true }
                },
                "required": ["id", "embedding"]
              }
            }
          }
        },
        "responses": { "200": { "description": "Upserted." } }
      }
    },
    "/v1/tenants/{tenant}/vector/{table}/topk": {
      "parameters": [
        { "$ref": "#/components/parameters/Tenant" },
        { "name": "table", "in": "path", "required": true, "schema": { "type": "string" } }
      ],
      "post": {
        "tags": ["Vector"],
        "summary": "Approximate nearest neighbors (HNSW)",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "vector": { "type": "array", "items": { "type": "number" } },
                  "k": { "type": "integer", "default": 10 },
                  "mode": { "type": "string", "enum": ["fast", "high_recall"], "default": "high_recall" }
                },
                "required": ["vector"]
              }
            }
          }
        },
        "responses": { "200": { "description": "Top-k matches with distances.", "content": { "application/json": { "schema": { "type": "array", "items": { "type": "object" } } } } } }
      }
    },
    "/v1/tenants/{tenant}/fts/{table}/{field}": {
      "parameters": [
        { "$ref": "#/components/parameters/Tenant" },
        { "name": "table", "in": "path", "required": true, "schema": { "type": "string" } },
        { "name": "field", "in": "path", "required": true, "schema": { "type": "string" } }
      ],
      "get": {
        "tags": ["FTS"],
        "summary": "BM25 full-text search",
        "parameters": [
          { "name": "q", "in": "query", "required": true, "schema": { "type": "string" } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 20 } }
        ],
        "responses": { "200": { "description": "Ranked matches.", "content": { "application/json": { "schema": { "type": "array", "items": { "type": "object" } } } } } }
      },
      "post": {
        "tags": ["FTS"],
        "summary": "Index a document for full-text search",
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "type": "object", "properties": { "doc_id": { "type": "string" }, "text": { "type": "string" } }, "required": ["doc_id", "text"] } } }
        },
        "responses": { "200": { "description": "Indexed." } }
      }
    },
    "/v1/tenants/{tenant}/graph/{schema}/neighbors": {
      "parameters": [
        { "$ref": "#/components/parameters/Tenant" },
        { "name": "schema", "in": "path", "required": true, "schema": { "type": "string" } },
        { "name": "node", "in": "query", "required": true, "schema": { "type": "string" }, "description": "Source node primary key." },
        { "name": "rel", "in": "query", "required": true, "schema": { "type": "string" }, "description": "Relation name." }
      ],
      "get": {
        "tags": ["Graph"],
        "summary": "Direct neighbors of a node along a relation",
        "responses": { "200": { "description": "Array of neighbor PKs.", "content": { "application/json": { "schema": { "type": "array", "items": { "type": "string" } } } } } }
      }
    },
    "/v1/tenants/{tenant}/graph/{schema}/bfs": {
      "parameters": [
        { "$ref": "#/components/parameters/Tenant" },
        { "name": "schema", "in": "path", "required": true, "schema": { "type": "string" } },
        { "name": "src", "in": "query", "required": true, "schema": { "type": "string" } },
        { "name": "rel", "in": "query", "required": true, "schema": { "type": "string" } },
        { "name": "depth", "in": "query", "schema": { "type": "integer", "default": 3 } }
      ],
      "get": {
        "tags": ["Graph"],
        "summary": "Breadth-first traversal",
        "responses": { "200": { "description": "BFS visit order with depths.", "content": { "application/json": { "schema": { "type": "array", "items": { "type": "object" } } } } } }
      }
    },
    "/v1/tenants/{tenant}/graph/{schema}/dijkstra": {
      "parameters": [
        { "$ref": "#/components/parameters/Tenant" },
        { "name": "schema", "in": "path", "required": true, "schema": { "type": "string" } },
        { "name": "src", "in": "query", "required": true, "schema": { "type": "string" } },
        { "name": "dst", "in": "query", "required": true, "schema": { "type": "string" } },
        { "name": "rel", "in": "query", "required": true, "schema": { "type": "string" } },
        { "name": "weight_field", "in": "query", "schema": { "type": "string" } }
      ],
      "get": {
        "tags": ["Graph"],
        "summary": "Weighted shortest path (Dijkstra)",
        "responses": { "200": { "description": "Path + total weight.", "content": { "application/json": { "schema": { "type": "object" } } } } }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "opaque-token",
        "description": "Static bearer token issued at instance provisioning. One token = full tenant access."
      }
    },
    "parameters": {
      "Tenant": {
        "name": "tenant",
        "in": "path",
        "required": true,
        "schema": { "type": "string" },
        "description": "Tenant ULID — the ID returned at provisioning."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": { "type": "string" },
              "message": { "type": "string" }
            },
            "required": ["code", "message"]
          }
        }
      },
      "SchemaRegisterResponse": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "description": "Schema ID (namespace.table)." },
          "tenant": { "type": "string", "description": "Tenant ULID." }
        },
        "required": ["id", "tenant"]
      }
    },
    "responses": {
      "BadRequest": { "description": "Bad request.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "Unauthorized": { "description": "Missing or invalid bearer.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "NotFound": { "description": "Not found.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "RateLimited": { "description": "Too many requests.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
    }
  }
}
