{
  "openapi": "3.1.0",
  "info": {
    "title": "Infino API",
    "description": "The Infino hosted data-plane API: per-database table operations — create, ingest, search, and SQL.",
    "version": "0.1.0"
  },
  "servers": [
    {
      "url": "https://api.platform.infino.ws",
      "description": "Infino Cloud"
    }
  ],
  "paths": {
    "/v1/append/{database}": {
      "post": {
        "tags": [
          "Rows"
        ],
        "summary": "Append rows",
        "description": "Append rows to a table. The body is an Arrow IPC stream, or a JSON `{\"data\": [...]}` envelope.",
        "operationId": "append",
        "parameters": [
          {
            "name": "database",
            "in": "path",
            "description": "Target database.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "table",
            "in": "query",
            "description": "Target table.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "description": "The rows to append: a JSON `{\"data\": [...]}` envelope of rows keyed by column name (`application/json`), or an Arrow IPC stream of one record batch (`application/vnd.apache.arrow.stream`).",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RowsEnvelope"
              }
            },
            "application/vnd.apache.arrow.stream": {
              "schema": {
                "$ref": "#/components/schemas/ArrowIpcRows"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Rows appended. Body is an Arrow IPC row stream (application/vnd.apache.arrow.stream), or a JSON `{\"data\": [...]}` envelope."
          },
          "400": {
            "description": "Invalid request body."
          },
          "401": {
            "description": "Missing or invalid API key."
          },
          "403": {
            "description": "The account already stores one of its limits — rows, or vectors (one per row of a table with a vector column) — so no more can be added. The response body names which limit was reached. Delete rows to free space; reads and deletes are never refused for this reason. Not transient: retrying without freeing space fails identically."
          },
          "404": {
            "description": "The target table does not exist. Append never creates a table — create it first with create_table."
          },
          "409": {
            "description": "Another write to the same table was in flight, so this one was not applied. A table takes one write at a time. Transient — reissue the identical request after the `Retry-After` interval, or batch more rows per request to need fewer of them."
          },
          "503": {
            "description": "The database's workers are still activating, or no capacity is free to place them. Transient — retry after the `Retry-After` interval."
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/v1/bm25_search/{database}": {
      "post": {
        "tags": [
          "Search"
        ],
        "summary": "BM25 full-text search",
        "description": "Ranked BM25 full-text search over a full-text-indexed column.",
        "operationId": "bm25_search",
        "parameters": [
          {
            "name": "database",
            "in": "path",
            "description": "Target database.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Bm25SearchRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Matching rows as an Arrow IPC stream (application/vnd.apache.arrow.stream), or JSON when the request sends `Accept: application/json`."
          },
          "400": {
            "description": "Invalid request body."
          },
          "401": {
            "description": "Missing or invalid API key."
          },
          "503": {
            "description": "The database's workers are still activating, or no capacity is free to place them. Transient — retry after the `Retry-After` interval."
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/v1/count/{database}": {
      "post": {
        "tags": [
          "Search"
        ],
        "summary": "Count matches",
        "description": "Count the rows matching a full-text query.",
        "operationId": "count",
        "parameters": [
          {
            "name": "database",
            "in": "path",
            "description": "Target database.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CountRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Match count as JSON `{\"count\": <n>}`."
          },
          "400": {
            "description": "Invalid request body."
          },
          "401": {
            "description": "Missing or invalid API key."
          },
          "503": {
            "description": "The database's workers are still activating, or no capacity is free to place them. Transient — retry after the `Retry-After` interval."
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/v1/create_table/{database}": {
      "post": {
        "tags": [
          "Tables"
        ],
        "summary": "Create a table",
        "description": "Create a table with an Arrow schema and optional full-text and vector indexes.",
        "operationId": "create_table",
        "parameters": [
          {
            "name": "database",
            "in": "path",
            "description": "Target database.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateTableRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Table created."
          },
          "400": {
            "description": "Invalid request body, or a malformed table name — use non-empty [A-Za-z0-9_-], at most 128 characters, not starting with '_'."
          },
          "401": {
            "description": "Missing or invalid API key."
          },
          "409": {
            "description": "Either the table name already exists — terminal, pick another name — or another catalog change was in flight, so this one was not applied. Every table in a database is created through one catalog. The second case carries a `Retry-After`; reissue the identical request after it."
          },
          "503": {
            "description": "The database's workers are still activating, or no capacity is free to place them. Transient — retry after the `Retry-After` interval."
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/v1/databases": {
      "get": {
        "tags": [
          "Databases"
        ],
        "summary": "List databases",
        "description": "List your account's databases and their state.",
        "operationId": "list_databases",
        "responses": {
          "200": {
            "description": "The account's databases.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListDatabasesResponse"
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      },
      "post": {
        "tags": [
          "Databases"
        ],
        "summary": "Create a database",
        "description": "Register a new database for your account.",
        "operationId": "create_database",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateDatabaseRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Database registered."
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "402": {
            "description": "The account has not completed onboarding.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "403": {
            "description": "The API key may not address this database, or the account is not entitled to storage bindings (BYOB is an enterprise feature).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "409": {
            "description": "Database already exists.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/v1/databases/{name}": {
      "delete": {
        "tags": [
          "Databases"
        ],
        "summary": "Delete a database",
        "description": "Begin deleting a database. Idempotent.",
        "operationId": "delete_database",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "The database name to delete.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Database deletion begun (idempotent)."
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "412": {
            "description": "The database changed concurrently; retry the request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/v1/databases/{name}/storage/verify": {
      "post": {
        "tags": [
          "Databases"
        ],
        "summary": "Verify a storage binding",
        "description": "Prove the database's bring-your-own-bucket grant end to end; workers start only after this passes.",
        "operationId": "verify_database_storage",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "description": "The database name.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "The binding verified; workers may start."
          },
          "400": {
            "description": "No binding, or the probe failed; the message names the failing stage.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "404": {
            "description": "No such database.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          },
          "410": {
            "description": "The database is being purged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBody"
                }
              }
            }
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/v1/delete/{database}": {
      "post": {
        "tags": [
          "Rows"
        ],
        "summary": "Delete rows",
        "description": "Delete rows matching a predicate. `table` and `predicate` are query parameters; no body.",
        "operationId": "delete",
        "parameters": [
          {
            "name": "database",
            "in": "path",
            "description": "Target database.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "table",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "predicate",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Row counts as JSON `{matched, n_tombstoned, n_not_found}`."
          },
          "401": {
            "description": "Missing or invalid API key."
          },
          "409": {
            "description": "Another write to the same table was in flight, so this one was not applied. A table takes one write at a time. Transient — reissue the identical request after the `Retry-After` interval, or batch more rows per request to need fewer of them."
          },
          "503": {
            "description": "The database's workers are still activating, or no capacity is free to place them. Transient — retry after the `Retry-After` interval."
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/v1/drop_table/{database}": {
      "post": {
        "tags": [
          "Tables"
        ],
        "summary": "Drop a table",
        "description": "Drop a table from the database.",
        "operationId": "drop_table",
        "parameters": [
          {
            "name": "database",
            "in": "path",
            "description": "Target database.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DropTableRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Table dropped."
          },
          "400": {
            "description": "Invalid request body."
          },
          "401": {
            "description": "Missing or invalid API key."
          },
          "409": {
            "description": "Another catalog change was in flight, so this one was not applied. Every table in a database is dropped through one catalog. Transient — reissue the identical request after the `Retry-After` interval."
          },
          "503": {
            "description": "The database's workers are still activating, or no capacity is free to place them. Transient — retry after the `Retry-After` interval."
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/v1/exact_match/{database}": {
      "post": {
        "tags": [
          "Search"
        ],
        "summary": "Exact match",
        "description": "Exact-value match over a column.",
        "operationId": "exact_match",
        "parameters": [
          {
            "name": "database",
            "in": "path",
            "description": "Target database.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ExactMatchRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Matching rows as an Arrow IPC stream (application/vnd.apache.arrow.stream), or JSON when the request sends `Accept: application/json`."
          },
          "400": {
            "description": "Invalid request body."
          },
          "401": {
            "description": "Missing or invalid API key."
          },
          "503": {
            "description": "The database's workers are still activating, or no capacity is free to place them. Transient — retry after the `Retry-After` interval."
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/v1/hybrid_search/{database}": {
      "post": {
        "tags": [
          "Search"
        ],
        "summary": "Hybrid search",
        "description": "Hybrid BM25 and vector search, fused with reciprocal-rank fusion.",
        "operationId": "hybrid_search",
        "parameters": [
          {
            "name": "database",
            "in": "path",
            "description": "Target database.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/HybridSearchRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Matching rows as an Arrow IPC stream (application/vnd.apache.arrow.stream), or JSON when the request sends `Accept: application/json`."
          },
          "400": {
            "description": "Invalid request body."
          },
          "401": {
            "description": "Missing or invalid API key."
          },
          "503": {
            "description": "The database's workers are still activating, or no capacity is free to place them. Transient — retry after the `Retry-After` interval."
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/v1/list_tables/{database}": {
      "post": {
        "tags": [
          "Tables"
        ],
        "summary": "List tables",
        "description": "List the tables in the database.",
        "operationId": "list_tables",
        "parameters": [
          {
            "name": "database",
            "in": "path",
            "description": "Target database.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "JSON array of table names."
          },
          "401": {
            "description": "Missing or invalid API key."
          },
          "503": {
            "description": "The database's workers are still activating, or no capacity is free to place them. Transient — retry after the `Retry-After` interval."
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/v1/query_sql/{database}": {
      "post": {
        "tags": [
          "Search"
        ],
        "summary": "Run a SQL query",
        "description": "Run a read-only SQL query across the database's tables.",
        "operationId": "sql_query",
        "parameters": [
          {
            "name": "database",
            "in": "path",
            "description": "Target database.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SqlQueryRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Matching rows as an Arrow IPC stream (application/vnd.apache.arrow.stream), or JSON when the request sends `Accept: application/json`."
          },
          "400": {
            "description": "Invalid request body."
          },
          "401": {
            "description": "Missing or invalid API key."
          },
          "503": {
            "description": "The database's workers are still activating, or no capacity is free to place them. Transient — retry after the `Retry-After` interval."
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/v1/schema/{database}": {
      "post": {
        "tags": [
          "Tables"
        ],
        "summary": "Describe a table's schema",
        "description": "Return a table's column schema.",
        "operationId": "schema",
        "parameters": [
          {
            "name": "database",
            "in": "path",
            "description": "Target database.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SchemaRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "JSON array of column descriptors."
          },
          "400": {
            "description": "Invalid request body."
          },
          "401": {
            "description": "Missing or invalid API key."
          },
          "503": {
            "description": "The database's workers are still activating, or no capacity is free to place them. Transient — retry after the `Retry-After` interval."
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/v1/token_match/{database}": {
      "post": {
        "tags": [
          "Search"
        ],
        "summary": "Token match",
        "description": "Unranked token match over a full-text-indexed column.",
        "operationId": "token_match",
        "parameters": [
          {
            "name": "database",
            "in": "path",
            "description": "Target database.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TokenMatchRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Matching rows as an Arrow IPC stream (application/vnd.apache.arrow.stream), or JSON when the request sends `Accept: application/json`."
          },
          "400": {
            "description": "Invalid request body."
          },
          "401": {
            "description": "Missing or invalid API key."
          },
          "503": {
            "description": "The database's workers are still activating, or no capacity is free to place them. Transient — retry after the `Retry-After` interval."
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/v1/update/{database}": {
      "post": {
        "tags": [
          "Rows"
        ],
        "summary": "Update rows",
        "description": "Replace rows matching a predicate. `table` and `predicate` are query parameters; the body carries the replacement rows (Arrow IPC or JSON).",
        "operationId": "update",
        "parameters": [
          {
            "name": "database",
            "in": "path",
            "description": "Target database.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "table",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "predicate",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "description": "The replacement rows, 1:1 with the rows the predicate matches: a JSON `{\"data\": [...]}` envelope of rows keyed by column name (`application/json`), or an Arrow IPC stream of one record batch (`application/vnd.apache.arrow.stream`).",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RowsEnvelope"
              }
            },
            "application/vnd.apache.arrow.stream": {
              "schema": {
                "$ref": "#/components/schemas/ArrowIpcRows"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Row counts as JSON `{matched, n_tombstoned, n_not_found}`. Body is the replacement rows as an Arrow IPC stream."
          },
          "400": {
            "description": "Invalid request."
          },
          "401": {
            "description": "Missing or invalid API key."
          },
          "403": {
            "description": "The account already stores one of its limits — rows, or vectors (one per row of a table with a vector column) — so no more can be added. The response body names which limit was reached. Delete rows to free space; reads and deletes are never refused for this reason. Not transient: retrying without freeing space fails identically."
          },
          "409": {
            "description": "Another write to the same table was in flight, so this one was not applied. A table takes one write at a time. Transient — reissue the identical request after the `Retry-After` interval, or batch more rows per request to need fewer of them."
          },
          "503": {
            "description": "The database's workers are still activating, or no capacity is free to place them. Transient — retry after the `Retry-After` interval."
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    },
    "/v1/vector_search/{database}": {
      "post": {
        "tags": [
          "Search"
        ],
        "summary": "Vector search",
        "description": "Vector (kNN) search over a vector column, with an optional full-text pre-filter.",
        "operationId": "vector_search",
        "parameters": [
          {
            "name": "database",
            "in": "path",
            "description": "Target database.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VectorSearchRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Matching rows as an Arrow IPC stream (application/vnd.apache.arrow.stream), or JSON when the request sends `Accept: application/json`."
          },
          "400": {
            "description": "Invalid request body."
          },
          "401": {
            "description": "Missing or invalid API key."
          },
          "503": {
            "description": "The database's workers are still activating, or no capacity is free to place them. Transient — retry after the `Retry-After` interval."
          }
        },
        "security": [
          {
            "api_key": []
          }
        ]
      }
    }
  },
  "components": {
    "schemas": {
      "ArrowIpcRows": {
        "type": "string",
        "format": "binary",
        "description": "A raw Arrow IPC stream request body: one record batch of rows, sent as\n`Content-Type: application/vnd.apache.arrow.stream`. The most efficient\ningest path — no JSON conversion; the batch's schema must match the\ntable's."
      },
      "Bm25SearchRequest": {
        "type": "object",
        "description": "`POST /v1/bm25_search/{database}`. Projection is optional (absent ⇒ the\nengine-native `_id` + `score`).",
        "required": [
          "table_name",
          "field_name",
          "query",
          "k",
          "mode"
        ],
        "properties": {
          "field_name": {
            "type": "string"
          },
          "k": {
            "type": "integer",
            "minimum": 0
          },
          "mode": {
            "$ref": "#/components/schemas/Mode"
          },
          "projection": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            }
          },
          "query": {
            "type": "string"
          },
          "stats": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/Stats",
                "description": "BM25 corpus statistics for idf scoring. Absent ⇒ the engine default\n(per-superfile); the engine SDK's remote transport always sends it."
              }
            ]
          },
          "table_name": {
            "type": "string"
          }
        },
        "additionalProperties": false
      },
      "CountRequest": {
        "type": "object",
        "description": "`POST /v1/count/{database}`. Count of rows matching a keyword query.",
        "required": [
          "table_name",
          "field_name",
          "query",
          "mode"
        ],
        "properties": {
          "field_name": {
            "type": "string"
          },
          "mode": {
            "$ref": "#/components/schemas/Mode"
          },
          "query": {
            "type": "string"
          },
          "table_name": {
            "type": "string"
          }
        },
        "additionalProperties": false
      },
      "CreateDatabaseRequest": {
        "type": "object",
        "description": "Create-database request.",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "The database name, unique within the account."
          },
          "storage": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/CreateDatabaseStorage",
                "description": "Bring-your-own-bucket: where this database's data should live. Omitted\nmeans platform-hosted storage, exactly as before this field existed."
              }
            ]
          }
        }
      },
      "CreateDatabaseResponse": {
        "type": "object",
        "description": "Create-database response. Empty for a platform-hosted database; a bound\none carries what the caller needs to finish the handshake.",
        "properties": {
          "storage": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/CreatedStorage",
                "description": "Present when the database was created with a storage binding."
              }
            ]
          }
        }
      },
      "CreateDatabaseStorage": {
        "oneOf": [
          {
            "type": "object",
            "description": "Amazon S3 (or an S3-compatible store via `endpoint`).",
            "required": [
              "bucket",
              "region",
              "role_arn",
              "provider"
            ],
            "properties": {
              "bucket": {
                "type": "string",
                "description": "The customer's bucket."
              },
              "endpoint": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Custom endpoint for an S3-compatible store (https only)."
              },
              "prefix": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Root inside the bucket under which everything the platform writes\nlives. Omitted roots at the bucket."
              },
              "provider": {
                "type": "string",
                "enum": [
                  "s3"
                ]
              },
              "region": {
                "type": "string",
                "description": "The bucket's region."
              },
              "requester_pays": {
                "type": "boolean",
                "description": "Whether the bucket has Requester Pays enabled."
              },
              "role_arn": {
                "type": "string",
                "description": "The customer-owned IAM role the platform will assume\n(`arn:aws:iam::<account>:role/<name>`)."
              }
            }
          },
          {
            "type": "object",
            "description": "Google Cloud Storage: the customer grants the platform's service\naccount an object role on the bucket.",
            "required": [
              "bucket",
              "region",
              "provider"
            ],
            "properties": {
              "bucket": {
                "type": "string",
                "description": "The customer's bucket."
              },
              "prefix": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Root inside the bucket. Omitted roots at the bucket."
              },
              "provider": {
                "type": "string",
                "enum": [
                  "gcs"
                ]
              },
              "region": {
                "type": "string",
                "description": "The bucket's region."
              }
            }
          },
          {
            "type": "object",
            "description": "Azure Blob Storage: the customer admin-consents the platform's Entra\napplication and grants it a data role on the storage account.",
            "required": [
              "container",
              "region",
              "tenant_id",
              "provider"
            ],
            "properties": {
              "container": {
                "type": "string",
                "description": "The customer's container."
              },
              "prefix": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Root inside the container. Omitted roots at the container."
              },
              "provider": {
                "type": "string",
                "enum": [
                  "azure"
                ]
              },
              "region": {
                "type": "string",
                "description": "The storage account's region."
              },
              "tenant_id": {
                "type": "string",
                "description": "The customer's Entra tenant id."
              }
            }
          }
        ],
        "description": "A requested storage binding, tagged by provider. Deliberately NOT the\nstored [`StorageBinding`] shape: the AWS external id is generated by the\nplatform during the create call and returned to the caller — accepting one\nfrom the request would let a caller reuse another binding's id and reopen\nthe confused-deputy hole the id exists to close."
      },
      "CreateTableRequest": {
        "type": "object",
        "description": "`POST /v1/create_table/{database}`.",
        "required": [
          "table_name"
        ],
        "properties": {
          "indexes": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/Indexes"
              }
            ]
          },
          "schema": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "$ref": "#/components/schemas/SchemaField"
            },
            "description": "JSON column descriptors. Exactly one of `schema` or `schema_ipc` is\nrequired. Cannot express nested types; use `schema_ipc` for those."
          },
          "schema_ipc": {
            "type": [
              "string",
              "null"
            ],
            "description": "The table's Arrow schema as a base64-encoded Arrow IPC stream carrying\nonly the schema message. Exactly one of `schema` or `schema_ipc` is\nrequired. Carries any Arrow type the engine accepts, nested included."
          },
          "table_name": {
            "type": "string"
          }
        },
        "additionalProperties": false
      },
      "CreatedStorage": {
        "type": "object",
        "description": "The binding half of a create response.",
        "required": [
          "verified"
        ],
        "properties": {
          "external_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "For AWS bindings: the external id to write into the role's trust\npolicy (`sts:ExternalId` condition). Returned exactly once, here."
          },
          "verified": {
            "type": "boolean",
            "description": "Whether the bind-time probe already passed. GCS and Azure try the\nprobe at create when the grant is already in place. AWS is always\n`false` here: the external id did not exist until this response, so\nthe customer cannot have written the trust policy yet — call\n`POST /v1/databases/{name}/storage/verify` (or the first query, which\nre-probes) once it is."
          }
        }
      },
      "DatabaseSummary": {
        "type": "object",
        "description": "One database in the account's list, with its lifecycle state.",
        "required": [
          "name",
          "state",
          "created_ms"
        ],
        "properties": {
          "created_ms": {
            "type": "integer",
            "format": "int64",
            "description": "Unix epoch milliseconds when the database was created, or `0` if unknown\n(a database registered before creation time was tracked).",
            "minimum": 0
          },
          "name": {
            "type": "string",
            "description": "The database name, unique within the account."
          },
          "state": {
            "type": "string",
            "description": "Lifecycle state: `registered` (usable), `purging` (being deleted), or\n`unreachable` (a bound database whose storage grant failed — restore\nthe grant and re-verify to restore service; the data is not lost)."
          }
        }
      },
      "DropTableRequest": {
        "type": "object",
        "description": "`POST /v1/drop_table/{database}`.",
        "required": [
          "table_name"
        ],
        "properties": {
          "purge": {
            "type": "boolean",
            "description": "Also delete the table's storage subtree after the catalog commit.\nDefaults to `true` (reclaim storage); pass `false` to only unregister\nthe table from the catalog and leave the bytes in place."
          },
          "table_name": {
            "type": "string"
          }
        },
        "additionalProperties": false
      },
      "ErrorBody": {
        "type": "object",
        "description": "A JSON error body.",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Human-readable error message."
          }
        }
      },
      "ExactMatchRequest": {
        "type": "object",
        "description": "`POST /v1/exact_match/{database}`. Unranked; projection is optional\n(absent ⇒ the engine-native `_id` + `score`).",
        "required": [
          "table_name",
          "field_name",
          "value"
        ],
        "properties": {
          "field_name": {
            "type": "string"
          },
          "projection": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            }
          },
          "table_name": {
            "type": "string"
          },
          "value": {
            "type": "string"
          }
        },
        "additionalProperties": false
      },
      "FtsColumn": {
        "type": "object",
        "description": "One FTS index declaration under `indexes.fts` — a column plus the analyzer\nits text is tokenized with (`{\"column\": \"body\", \"analyzer\": \"standard\"}`).\n`analyzer` is optional and, when omitted, the engine's default `ascii_lower`\napplies — the same default a bare-string entry gets (see [`FtsIndex`]).",
        "required": [
          "column"
        ],
        "properties": {
          "analyzer": {
            "type": [
              "string",
              "null"
            ],
            "description": "Analyzer name (`\"ascii_lower\"` or `\"standard\"`). Omitted means the\nengine default, `ascii_lower`."
          },
          "column": {
            "type": "string"
          }
        },
        "additionalProperties": false
      },
      "FtsIndex": {
        "oneOf": [
          {
            "type": "string",
            "description": "`\"body\"` — index the column with the default analyzer."
          },
          {
            "$ref": "#/components/schemas/FtsColumn",
            "description": "`{\"column\": \"body\", \"analyzer\": \"standard\"}`."
          }
        ],
        "description": "One entry in `indexes.fts`. Either a bare column name — which uses the\nengine's default `ascii_lower` analyzer — or a `{column, analyzer}` object\nthat names the analyzer explicitly. The bare-string form keeps clients that\nsend `\"fts\": [\"body\"]` working unchanged. An analyzer applies per column,\nnot per table."
      },
      "HybridSearchRequest": {
        "type": "object",
        "description": "`POST /v1/hybrid_search/{database}`. BM25 + vector fused with RRF.\nProjection is optional; vector-leg serving is engine-decided.",
        "required": [
          "table_name",
          "text_field",
          "text_query",
          "mode",
          "vector_field",
          "vector_query",
          "k"
        ],
        "properties": {
          "k": {
            "type": "integer",
            "minimum": 0
          },
          "mode": {
            "$ref": "#/components/schemas/Mode"
          },
          "projection": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            }
          },
          "table_name": {
            "type": "string"
          },
          "text_field": {
            "type": "string"
          },
          "text_query": {
            "type": "string"
          },
          "vector_field": {
            "type": "string"
          },
          "vector_query": {
            "type": "array",
            "items": {
              "type": "number",
              "format": "float"
            }
          }
        },
        "additionalProperties": false
      },
      "Indexes": {
        "type": "object",
        "description": "Index declarations for `create_table`.",
        "properties": {
          "fts": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "$ref": "#/components/schemas/FtsIndex"
            },
            "description": "FTS index declarations — a bare column name (default `ascii_lower`\nanalyzer) or a `{column, analyzer}` object per column."
          },
          "vector": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "$ref": "#/components/schemas/VectorIndex"
            },
            "description": "Vector index declarations."
          }
        },
        "additionalProperties": false
      },
      "ListDatabasesResponse": {
        "type": "object",
        "description": "The databases in your account.",
        "required": [
          "databases"
        ],
        "properties": {
          "databases": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DatabaseSummary"
            },
            "description": "The account's databases, order unspecified."
          }
        }
      },
      "Metric": {
        "type": "string",
        "description": "Vector distance metric. Accepted case-insensitively, with the aliases\n`l2` → `l2sq` and `dot` → `negdot`; serialized canonically.",
        "enum": [
          "cosine",
          "l2sq",
          "negdot"
        ]
      },
      "Mode": {
        "type": "string",
        "description": "Boolean mode for a multi-term FTS query. Accepted case-insensitively on the\nwire (`\"or\"`, `\"Or\"`, `\"OR\"`); serialized canonically lowercase.",
        "enum": [
          "or",
          "and"
        ]
      },
      "RowsEnvelope": {
        "type": "object",
        "description": "JSON row envelope for `POST /v1/append/{database}` and\n`POST /v1/update/{database}` — the `Content-Type: application/json`\nalternative to an Arrow IPC stream body. Rows are JSON objects keyed by\ncolumn name, converted server-side into one Arrow batch against the\ntable's schema.",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Rows as JSON objects keyed by column name."
          }
        },
        "additionalProperties": false
      },
      "SchemaField": {
        "type": "object",
        "description": "One column in a `create_table` schema. A scalar column is `{name, type}` where `type` is a scalar spelling (`\"i32\"`, `\"large_utf8\"`, …); a vector column is `{name, type: \"vector\", dim}`; a list column is `{name, type: \"list\", item}`. `dim` is required for `\"vector\"` and `item` for `\"list\"`.",
        "required": [
          "name",
          "type"
        ],
        "properties": {
          "dim": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Fixed length, required for `type: \"vector\"`. Must be in [1, 4096].",
            "maximum": 4096,
            "minimum": 1
          },
          "item": {
            "type": [
              "string",
              "null"
            ],
            "description": "Element scalar type, required for `type: \"list\"`."
          },
          "name": {
            "type": "string",
            "description": "Column name."
          },
          "nullable": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Defaults to `true` when omitted."
          },
          "type": {
            "type": "string",
            "description": "Scalar spelling, or `\"vector\"` / `\"list\"`."
          }
        },
        "additionalProperties": false
      },
      "SchemaRequest": {
        "type": "object",
        "description": "`POST /v1/schema/{database}`.",
        "required": [
          "table_name"
        ],
        "properties": {
          "encoding": {
            "type": [
              "string",
              "null"
            ],
            "description": "Response encoding. Omitted (the default) returns the JSON column\ndescriptors; `\"ipc\"` returns an Arrow IPC schema message, which is the\nonly form that can carry a nested column type."
          },
          "table_name": {
            "type": "string"
          }
        },
        "additionalProperties": false
      },
      "SqlQueryRequest": {
        "type": "object",
        "description": "`POST /v1/sql_query/{database}`.",
        "required": [
          "query"
        ],
        "properties": {
          "query": {
            "type": "string"
          }
        },
        "additionalProperties": false
      },
      "Stats": {
        "type": "string",
        "description": "Which BM25 corpus statistics to score term rarity (idf) with. Accepted\ncase-insensitively on the wire (`\"per_superfile\"`, `\"global\"`); serialized\ncanonically. Absent on a request ⇒ the engine default (per-superfile).",
        "enum": [
          "per_superfile",
          "global"
        ]
      },
      "TokenMatchRequest": {
        "type": "object",
        "description": "`POST /v1/token_match/{database}`. Unranked; projection is optional\n(absent ⇒ the engine-native `_id` + `score`).",
        "required": [
          "table_name",
          "field_name",
          "query",
          "mode"
        ],
        "properties": {
          "field_name": {
            "type": "string"
          },
          "mode": {
            "$ref": "#/components/schemas/Mode"
          },
          "projection": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            }
          },
          "query": {
            "type": "string"
          },
          "table_name": {
            "type": "string"
          }
        },
        "additionalProperties": false
      },
      "VectorFilter": {
        "type": "object",
        "description": "Optional text pre-filter for `vector_search`: kNN ranks only among rows\nwhose FTS-indexed `field_name` matches `query`.",
        "required": [
          "field_name",
          "query",
          "mode"
        ],
        "properties": {
          "field_name": {
            "type": "string"
          },
          "mode": {
            "$ref": "#/components/schemas/Mode"
          },
          "query": {
            "type": "string"
          }
        },
        "additionalProperties": false
      },
      "VectorIndex": {
        "type": "object",
        "description": "One vector index declaration under `indexes.vector`.",
        "required": [
          "column",
          "metric"
        ],
        "properties": {
          "column": {
            "type": "string"
          },
          "dim": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Redundant with the schema column's declared width; the server resolves\nthe dimension from the schema, so this is optional and, if given, must\nagree.",
            "minimum": 0
          },
          "metric": {
            "$ref": "#/components/schemas/Metric"
          }
        },
        "additionalProperties": false
      },
      "VectorSearchRequest": {
        "type": "object",
        "description": "`POST /v1/vector_search/{database}`. Projection is optional (absent ⇒ the\nengine-native `_id` + `score`); `filter` is an optional pushdown text\npre-filter. Probe width and rerank budget are engine-decided (drain-time\ncalibration) — there are no tuning knobs.",
        "required": [
          "table_name",
          "field_name",
          "query",
          "k"
        ],
        "properties": {
          "field_name": {
            "type": "string"
          },
          "filter": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/VectorFilter"
              }
            ]
          },
          "k": {
            "type": "integer",
            "minimum": 0
          },
          "projection": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            }
          },
          "query": {
            "type": "array",
            "items": {
              "type": "number",
              "format": "float"
            }
          },
          "table_name": {
            "type": "string"
          }
        },
        "additionalProperties": false
      }
    },
    "securitySchemes": {
      "api_key": {
        "type": "http",
        "scheme": "bearer"
      },
      "session_cookie": {
        "type": "apiKey",
        "in": "cookie",
        "name": "infino_session"
      },
      "session_token": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Session-Token"
      }
    }
  },
  "security": [
    {
      "api_key": []
    }
  ],
  "tags": [
    {
      "name": "Databases",
      "description": "Create, list, and delete the databases in your account."
    },
    {
      "name": "Tables",
      "description": "Create, drop, and list tables, and describe a table's schema."
    },
    {
      "name": "Rows",
      "description": "Append, update, and delete rows."
    },
    {
      "name": "Search",
      "description": "BM25, vector, and hybrid search, token and exact match, count, and SQL."
    }
  ]
}