{
  "openapi": "3.1.0",
  "info": {
    "title": "ChatData Sync API",
    "version": "1.0.0",
    "description": "Schema generation, schema migration, and sync endpoints for ChatData Sync."
  },
  "servers": [
    {
      "url": "https://chatdatasync.com",
      "description": "Production deployment"
    }
  ],
  "paths": {
    "/api/health": {
      "get": {
        "summary": "Service health",
        "operationId": "getHealth",
        "responses": {
          "200": {
            "description": "Health status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthOkResponse"
                },
                "example": {
                  "status": "ok",
                  "firebaseAdmin": true
                }
              }
            }
          },
          "503": {
            "description": "Service is shutting down",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthShuttingDownResponse"
                },
                "example": {
                  "status": "shutting_down",
                  "firebaseAdmin": false
                }
              }
            }
          }
        }
      }
    },
    "/api/health/live": {
      "get": {
        "summary": "Liveness health",
        "operationId": "getHealthLive",
        "responses": {
          "200": {
            "description": "Service is live",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthLiveOkResponse"
                },
                "example": {
                  "status": "ok"
                }
              }
            }
          },
          "503": {
            "description": "Service is shutting down",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthLiveShuttingDownResponse"
                },
                "example": {
                  "status": "shutting_down"
                }
              }
            }
          }
        }
      }
    },
    "/api/health/ready": {
      "get": {
        "summary": "Readiness health",
        "operationId": "getHealthReady",
        "responses": {
          "200": {
            "description": "Service is ready",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthReadyResponse"
                },
                "example": {
                  "status": "ready",
                  "firebaseAdmin": true
                }
              }
            }
          },
          "503": {
            "description": "Service is not ready",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthNotReadyResponse"
                },
                "example": {
                  "status": "not_ready",
                  "firebaseAdmin": false
                }
              }
            }
          }
        }
      }
    },
    "/api/openapi.json": {
      "get": {
        "summary": "Get OpenAPI contract",
        "operationId": "getOpenApiSpec",
        "responses": {
          "200": {
            "description": "OpenAPI 3.1 spec",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "openapi": {
                      "type": "string"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/OpenApiUnavailable"
          }
        }
      }
    },
    "/api/v1/sync/context": {
      "get": {
        "summary": "Get API key scoped sync context",
        "operationId": "getSyncContext",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sync context for the project associated with provided API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SyncContextResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "description": "Returns the tracker name, default table, and available tables for the project scoped to the supplied x-api-key. Use this to resolve table context instead of asking the user for project identifiers."
      }
    },
    "/api/v1/sync/current/{table}": {
      "get": {
        "summary": "List latest records for a table",
        "operationId": "listCurrentSyncRecords",
        "parameters": [
          {
            "name": "table",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-zA-Z0-9_-]{1,128}$"
            }
          },
          {
            "name": "unpaidOnly",
            "in": "query",
            "required": false,
            "description": "When true, returns only unpaid records. Must be the string true or false.",
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Inclusive lower bound for createdAt. Accepts ISO 8601 datetime or YYYY-MM-DD (UTC).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Inclusive upper bound for createdAt. Accepts ISO 8601 datetime or YYYY-MM-DD (UTC).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum records to return. Integer from 1 to 200. Defaults to 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          }
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Records list",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SyncListResponse"
                },
                "example": {
                  "table": "tasks",
                  "items": [
                    {
                      "id": "a1b2c3",
                      "data": {
                        "title": "Plant tomatoes",
                        "completed": false
                      },
                      "createdAt": "2026-05-09T12:00:00.000Z",
                      "updatedAt": "2026-05-09T12:00:00.000Z"
                    }
                  ],
                  "filters": {
                    "unpaidOnly": true,
                    "from": "2026-05-01T00:00:00.000Z",
                    "to": "2026-05-09T23:59:59.999Z",
                    "limit": 25
                  },
                  "summary": {
                    "scannedCount": 25,
                    "returnedCount": 7,
                    "unpaidCount": 7,
                    "unpaidAmountTotal": 420
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/ProjectNotFound"
          },
          "405": {
            "$ref": "#/components/responses/MethodNotAllowed"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "description": "Use API key scoped context; never ask for project IDs or backend identifiers. If the table is unclear, call getSyncContext and use the default table guidance. Ask only for missing business fields needed to complete the request."
      },
      "post": {
        "summary": "Create one sync record in a table",
        "operationId": "createCurrentSyncRecord",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SyncRecordInput"
              },
              "example": {
                "record_json": "{\"title\":\"Plant tomatoes\",\"completed\":false,\"notes\":\"Use raised bed\"}"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Record created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SyncCreateResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/ProjectNotFound"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "parameters": [
          {
            "name": "table",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-zA-Z0-9_-]{1,128}$"
            }
          }
        ],
        "description": "Use API key scoped context; never ask for project IDs or backend identifiers. If the table is unclear, call getSyncContext and use the default table guidance. Ask only for missing business fields needed to complete the request."
      },
      "patch": {
        "summary": "Update one sync record in a table",
        "operationId": "updateCurrentSyncRecord",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SyncUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Record updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SyncCreateResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/ProjectNotFound"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "parameters": [
          {
            "name": "table",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-zA-Z0-9_-]{1,128}$"
            }
          }
        ],
        "description": "Use the API key scoped context and never ask the user for a project ID or backend identifier. If the destination table is unclear, call getSyncContext first. Use record id plus partial fields to update only what changed."
      }
    },
    "/api/v1/sync/current": {
      "get": {
        "summary": "List latest records from the default table",
        "operationId": "listCurrentDefaultSyncRecords",
        "parameters": [
          {
            "name": "unpaidOnly",
            "in": "query",
            "required": false,
            "description": "When true, returns only unpaid records. Must be the string true or false.",
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Inclusive lower bound for createdAt. Accepts ISO 8601 datetime or YYYY-MM-DD (UTC).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Inclusive upper bound for createdAt. Accepts ISO 8601 datetime or YYYY-MM-DD (UTC).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum records to return. Integer from 1 to 200. Defaults to 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          }
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Records list",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SyncListResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/ProjectNotFound"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "description": "Use API key scoped context; never ask for project IDs or backend identifiers. If the table is unclear, call getSyncContext and use the default table guidance. Ask only for missing business fields needed to complete the request."
      },
      "post": {
        "summary": "Create one sync record in the default table",
        "operationId": "createCurrentDefaultSyncRecord",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SyncRecordInput"
              },
              "example": {
                "record_json": "{\"title\":\"Plant tomatoes\",\"completed\":false,\"notes\":\"Use raised bed\"}"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Record created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SyncCreateResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/ProjectNotFound"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "description": "Use API key scoped context; never ask for project IDs or backend identifiers. If the table is unclear, call getSyncContext and use the default table guidance. Ask only for missing business fields needed to complete the request."
      },
      "patch": {
        "summary": "Update one sync record in the default table",
        "operationId": "updateCurrentDefaultSyncRecord",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SyncUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Record updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SyncCreateResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/ProjectNotFound"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "description": "Use the API key scoped context and never ask the user for a project ID or backend identifier. Use record id plus partial fields to update only what changed."
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key"
      }
    },
    "parameters": {
      "table": {
        "name": "table",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "pattern": "^[a-zA-Z0-9_-]{1,128}$"
        }
      },
      "unpaidOnly": {
        "name": "unpaidOnly",
        "in": "query",
        "required": false,
        "description": "When true, returns only unpaid records. Must be the string true or false.",
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      },
      "from": {
        "name": "from",
        "in": "query",
        "required": false,
        "description": "Inclusive lower bound for createdAt. Accepts ISO 8601 datetime or YYYY-MM-DD (UTC).",
        "schema": {
          "type": "string"
        }
      },
      "to": {
        "name": "to",
        "in": "query",
        "required": false,
        "description": "Inclusive upper bound for createdAt. Accepts ISO 8601 datetime or YYYY-MM-DD (UTC).",
        "schema": {
          "type": "string"
        }
      },
      "limit": {
        "name": "limit",
        "in": "query",
        "required": false,
        "description": "Maximum records to return. Integer from 1 to 200. Defaults to 50.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 200
        }
      }
    },
    "schemas": {
      "HealthLiveOkResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "status"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ok"
            ]
          }
        }
      },
      "HealthLiveShuttingDownResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "status"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "shutting_down"
            ]
          }
        }
      },
      "HealthOkResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "status",
          "firebaseAdmin"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ok"
            ]
          },
          "firebaseAdmin": {
            "type": "boolean"
          }
        }
      },
      "HealthShuttingDownResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "status",
          "firebaseAdmin"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "shutting_down"
            ]
          },
          "firebaseAdmin": {
            "type": "boolean"
          }
        }
      },
      "HealthReadyResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "status",
          "firebaseAdmin"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ready"
            ]
          },
          "firebaseAdmin": {
            "type": "boolean"
          }
        }
      },
      "HealthNotReadyResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "status",
          "firebaseAdmin"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "not_ready"
            ]
          },
          "firebaseAdmin": {
            "type": "boolean"
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "additionalProperties": true,
        "required": [
          "error",
          "code",
          "requestId"
        ],
        "properties": {
          "error": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "requestId": {
            "type": "string"
          }
        }
      },
      "Field": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "name",
          "type",
          "description",
          "required"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128
          },
          "type": {
            "type": "string",
            "enum": [
              "text",
              "number",
              "boolean",
              "date",
              "time",
              "choice"
            ]
          },
          "description": {
            "type": "string",
            "minLength": 1
          },
          "required": {
            "type": "boolean"
          },
          "choices": {
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1
            },
            "minItems": 1
          }
        }
      },
      "Table": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "table_name",
          "description",
          "fields"
        ],
        "properties": {
          "table_name": {
            "type": "string",
            "pattern": "^[a-zA-Z0-9_-]+$"
          },
          "description": {
            "type": "string",
            "minLength": 1
          },
          "fields": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Field"
            },
            "minItems": 1
          }
        }
      },
      "GeneratedSchema": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "friendly_name",
          "tables"
        ],
        "properties": {
          "friendly_name": {
            "type": "string",
            "minLength": 1
          },
          "tables": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Table"
            },
            "minItems": 1
          }
        }
      },
      "GenerateSchemaRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "prompt"
        ],
        "properties": {
          "prompt": {
            "type": "string",
            "minLength": 1
          },
          "systemInstructions": {
            "type": "string"
          }
        }
      },
      "MigrateSchemaRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "currentSchema",
          "modificationRequest"
        ],
        "properties": {
          "currentSchema": {
            "$ref": "#/components/schemas/GeneratedSchema"
          },
          "modificationRequest": {
            "type": "string",
            "minLength": 1
          },
          "systemInstructions": {
            "type": "string"
          },
          "allowDestructiveChanges": {
            "type": "boolean",
            "default": false
          }
        }
      },
      "ProjectMigrateRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "prompt"
        ],
        "properties": {
          "prompt": {
            "type": "string",
            "minLength": 1
          },
          "allowDestructiveChanges": {
            "type": "boolean",
            "default": false
          }
        }
      },
      "ProjectCreateRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "name",
          "description",
          "schema"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 160
          },
          "description": {
            "type": "string",
            "minLength": 1
          },
          "schema": {
            "$ref": "#/components/schemas/GeneratedSchema"
          }
        }
      },
      "ProjectCreateResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "projectId",
          "apiKey",
          "message"
        ],
        "properties": {
          "projectId": {
            "type": "string",
            "pattern": "^[a-zA-Z0-9_-]{1,128}$"
          },
          "apiKey": {
            "type": "string",
            "minLength": 20
          },
          "message": {
            "type": "string"
          }
        }
      },
      "ProjectUpdateRequest": {
        "type": "object",
        "additionalProperties": false,
        "minProperties": 1,
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 160
          },
          "description": {
            "type": "string",
            "minLength": 1
          },
          "schema": {
            "$ref": "#/components/schemas/GeneratedSchema"
          }
        }
      },
      "ProjectUpdateResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "message",
          "projectId",
          "updatedAt"
        ],
        "properties": {
          "message": {
            "type": "string"
          },
          "projectId": {
            "type": "string",
            "pattern": "^[a-zA-Z0-9_-]{1,128}$"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ProjectDeleteResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "message",
          "projectId"
        ],
        "properties": {
          "message": {
            "type": "string"
          },
          "projectId": {
            "type": "string",
            "pattern": "^[a-zA-Z0-9_-]{1,128}$"
          }
        }
      },
      "ProjectItemsImportRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "rows"
        ],
        "properties": {
          "table": {
            "type": "string",
            "pattern": "^[a-zA-Z0-9_-]{1,128}$"
          },
          "rows": {
            "type": "array",
            "minItems": 1,
            "maxItems": 200,
            "items": {
              "$ref": "#/components/schemas/SyncRecordInput"
            }
          }
        }
      },
      "ProjectItemsImportResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "message",
          "table",
          "importedCount"
        ],
        "properties": {
          "message": {
            "type": "string"
          },
          "table": {
            "type": "string"
          },
          "importedCount": {
            "type": "integer",
            "minimum": 1
          }
        }
      },
      "ProjectItemsDeleteRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "ids"
        ],
        "properties": {
          "table": {
            "type": "string",
            "pattern": "^[a-zA-Z0-9_-]{1,128}$"
          },
          "ids": {
            "type": "array",
            "minItems": 1,
            "maxItems": 200,
            "items": {
              "type": "string",
              "pattern": "^[a-zA-Z0-9_-]{1,160}$"
            }
          }
        }
      },
      "ProjectItemsDeleteResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "message",
          "table",
          "deletedCount"
        ],
        "properties": {
          "message": {
            "type": "string"
          },
          "table": {
            "type": "string"
          },
          "deletedCount": {
            "type": "integer",
            "minimum": 1
          }
        }
      },
      "SyncRecordInput": {
        "type": "object",
        "description": "Arbitrary JSON object representing a row payload.",
        "additionalProperties": false,
        "required": [
          "record_json"
        ],
        "properties": {
          "record_json": {
            "type": "string",
            "description": "JSON object string with exact field names from getSyncContext (for example: {\"client_name\":\"Test Client\",\"lead_status\":\"New\"})."
          },
          "record": {
            "type": "object",
            "additionalProperties": true,
            "properties": {},
            "description": "Optional object form for clients that support arbitrary object properties."
          }
        }
      },
      "SyncUpdateRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "data"
        ],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[a-zA-Z0-9_-]{1,160}$"
          },
          "data": {
            "$ref": "#/components/schemas/SyncRecordInput"
          }
        }
      },
      "SyncRecord": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "data",
          "createdAt",
          "updatedAt"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "data": {
            "type": "object",
            "additionalProperties": true
          },
          "createdAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updatedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "SyncListResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "table",
          "items"
        ],
        "properties": {
          "table": {
            "type": "string"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SyncRecord"
            }
          },
          "filters": {
            "$ref": "#/components/schemas/SyncListFilters"
          },
          "summary": {
            "$ref": "#/components/schemas/SyncListSummary"
          }
        }
      },
      "SyncListFilters": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "unpaidOnly",
          "from",
          "to",
          "limit"
        ],
        "properties": {
          "unpaidOnly": {
            "type": "boolean"
          },
          "from": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "to": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 200
          }
        }
      },
      "SyncListSummary": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "scannedCount",
          "returnedCount",
          "unpaidCount",
          "unpaidAmountTotal"
        ],
        "properties": {
          "scannedCount": {
            "type": "integer",
            "minimum": 0
          },
          "returnedCount": {
            "type": "integer",
            "minimum": 0
          },
          "unpaidCount": {
            "type": "integer",
            "minimum": 0
          },
          "unpaidAmountTotal": {
            "type": "number"
          }
        }
      },
      "SyncCreateResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "message",
          "table",
          "record"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "table": {
            "type": "string"
          },
          "record": {
            "$ref": "#/components/schemas/SyncRecord"
          }
        }
      },
      "SchemaMigrateResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "message",
          "schema"
        ],
        "properties": {
          "message": {
            "type": "string"
          },
          "schema": {
            "$ref": "#/components/schemas/GeneratedSchema"
          }
        }
      },
      "ApiKeyRotateResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "message",
          "projectId",
          "apiKey",
          "updatedAt"
        ],
        "properties": {
          "message": {
            "type": "string"
          },
          "projectId": {
            "type": "string",
            "pattern": "^[a-zA-Z0-9_-]{1,128}$"
          },
          "apiKey": {
            "type": "string",
            "minLength": 32
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ConnectionHealthResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "status",
          "checkedAt",
          "lastSuccessfulSyncAt",
          "message"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "healthy",
              "degraded",
              "offline"
            ]
          },
          "checkedAt": {
            "type": "string",
            "format": "date-time"
          },
          "lastSuccessfulSyncAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "ProjectActivityRecord": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "eventType",
          "status",
          "timestamp",
          "summary",
          "category"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "eventType": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "success",
              "failure"
            ]
          },
          "timestamp": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "summary": {
            "type": "string"
          },
          "category": {
            "type": "string",
            "enum": [
              "sync",
              "security",
              "data_setup",
              "project",
              "system"
            ]
          },
          "target": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "resource": {
                "type": "string"
              },
              "table": {
                "type": "string"
              },
              "docId": {
                "type": "string"
              }
            }
          },
          "errorCode": {
            "type": "string"
          }
        }
      },
      "ProjectActivityResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "items",
          "limit"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProjectActivityRecord"
            }
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 50
          }
        }
      },
      "SyncContextTableSummary": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "table_name",
          "description",
          "fields"
        ],
        "properties": {
          "table_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "fields": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Field"
            }
          }
        }
      },
      "SyncContextResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "name",
          "description",
          "defaultTable",
          "tables",
          "writeGuidance"
        ],
        "properties": {
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "defaultTable": {
            "type": "string"
          },
          "tables": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SyncContextTableSummary"
            }
          },
          "writeGuidance": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "whenTableMissing",
              "askOnlyForMissingRequiredFields",
              "rejectUnknownFields"
            ],
            "properties": {
              "whenTableMissing": {
                "type": "string",
                "enum": [
                  "use_default_table"
                ]
              },
              "askOnlyForMissingRequiredFields": {
                "type": "boolean"
              },
              "rejectUnknownFields": {
                "type": "boolean"
              }
            }
          }
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Request payload or parameters invalid",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Authentication credentials missing, invalid, revoked, or blocked by account verification policy",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Forbidden": {
        "description": "Authenticated but not authorized for this resource",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "ProjectNotFound": {
        "description": "Project not found",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "MethodNotAllowed": {
        "description": "HTTP method is not supported for this route",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "PayloadTooLarge": {
        "description": "Payload exceeds configured limits",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Rate limit exceeded",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "ServiceUnavailable": {
        "description": "Backend dependency unavailable",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "AiUnavailable": {
        "description": "AI integration unavailable",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "AiGenerationFailed": {
        "description": "AI schema generation failed",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "AiMigrationFailed": {
        "description": "AI schema migration failed",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "SchemaMigrationFailed": {
        "description": "Schema migration failed",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "OpenApiUnavailable": {
        "description": "OpenAPI spec is unavailable",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "InternalError": {
        "description": "Unexpected server error",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      }
    }
  }
}
