{
  "openapi": "3.0.3",
  "info": {
    "title": "PropDesc-AI API",
    "version": "1.0.0",
    "description": "PropDesc-AI generates one real estate property description per call from structured property attributes, with optional target audience and location-area voice. It writes only from the data it is given and keeps framing on the property and area, never the type of resident (Fair Housing guardrails). It returns one description synchronously per call. It takes text attributes only (no photos) and does not support batch generation.\n\nAuthentication: send your API key in the `x-api-key` header. Get a key by signing up on https://oculix.io/docs/propdesc/. Each successful call uses 1 credit from your quota; an identical repeat of a recent request can be answered from a short-lived cache without using a credit (the response then carries `cached: true`). When the quota is used up the API returns 402.",
    "contact": {
      "name": "Oculix LLC",
      "url": "https://oculix.io",
      "email": "info@oculix.net"
    },
    "license": {
      "name": "Proprietary",
      "url": "https://oculix.io/legal/terms/"
    }
  },
  "servers": [
    {
      "url": "https://api.propdescai.io",
      "description": "Production"
    }
  ],
  "externalDocs": {
    "description": "Documentation and live widget",
    "url": "https://oculix.io/docs/propdesc/"
  },
  "components": {
    "securitySchemes": {
      "ApiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key"
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          },
          "detail": {
            "type": "string"
          },
          "supportedMethods": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "error"
        ]
      }
    }
  },
  "security": [
    {
      "ApiKey": []
    }
  ],
  "paths": {
    "/v1/propdesc/generate": {
      "post": {
        "summary": "Generate one property description",
        "operationId": "generateListing",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "propertyAttributes"
                ],
                "properties": {
                  "propertyAttributes": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "Structured attributes such as beds, baths and sqft. If `city`, `state` or `zip` is present, the area's current character is looked up with Google Search to inform tone.",
                    "example": {
                      "beds": 3,
                      "baths": 2,
                      "sqft": 1850,
                      "city": "Austin",
                      "state": "TX"
                    }
                  },
                  "targetAudience": {
                    "type": "string",
                    "enum": [
                      "investor",
                      "primary_home_owner",
                      "commercial",
                      "rental_tenant"
                    ],
                    "description": "Optional. Changes tone and word choice. Unrecognised values are ignored, not rejected."
                  },
                  "locationArea": {
                    "type": "string",
                    "enum": [
                      "in_town",
                      "suburbs",
                      "rural"
                    ],
                    "description": "Optional. Changes tone and word choice. Unrecognised values are ignored, not rejected."
                  },
                  "additionalContext": {
                    "type": "string",
                    "description": "Optional extra text to incorporate."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Generated description",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "status",
                    "generatedListing"
                  ],
                  "properties": {
                    "status": {
                      "type": "string",
                      "example": "success"
                    },
                    "generatedListing": {
                      "type": "string"
                    },
                    "cached": {
                      "type": "boolean",
                      "description": "Present and true when an identical earlier request was served from cache."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing x-api-key or propertyAttributes",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Bad Request"
                }
              }
            }
          },
          "401": {
            "description": "Unknown or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Unauthorized"
                }
              }
            }
          },
          "402": {
            "description": "Quota depleted: the key has no credits left",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Quota Depleted"
                }
              }
            }
          },
          "500": {
            "description": "Generation failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "string"
                }
              }
            }
          }
        }
      }
    },
    "/v1/usage": {
      "get": {
        "summary": "Remaining quota and call counts",
        "description": "Served by the auth service, not the product API. Returns the remaining credit quota for the key and a call-count breakdown.",
        "operationId": "getUsage",
        "servers": [
          {
            "url": "https://auth.propdescai.io"
          }
        ],
        "security": [
          {
            "ApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Quota and usage",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tenantId": {
                      "type": "string"
                    },
                    "product": {
                      "type": "string"
                    },
                    "remainingCreditQuota": {
                      "type": "integer"
                    },
                    "includedQuota": {
                      "type": "integer"
                    },
                    "usage": {
                      "type": "object",
                      "properties": {
                        "totalCalls": {
                          "type": "integer"
                        },
                        "callsLast30Days": {
                          "type": "integer"
                        },
                        "lastCallAt": {
                          "type": "string",
                          "nullable": true
                        },
                        "byEndpoint": {
                          "type": "array",
                          "items": {
                            "type": "object"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing x-api-key header",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Missing x-api-key header"
                }
              }
            }
          },
          "401": {
            "description": "Unknown key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Unauthorized"
                }
              }
            }
          },
          "500": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "string"
                }
              }
            }
          }
        }
      }
    }
  }
}
