{
  "openapi": "3.1.0",
  "info": {
    "title": "ImmoWP API",
    "version": "1.0.0",
    "description": "Real-estate listings gateway. Normalize properties from 40+ CRMs for WordPress, Meerweb, and headless consumers.\n\nDocs: https://www.immowp.fr/docs\nLLM index: https://www.immowp.fr/llms.txt",
    "contact": {
      "name": "ImmoWP Support",
      "url": "https://www.immowp.fr/contact"
    },
    "license": {
      "name": "Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://api.immowp.com",
      "description": "Production"
    }
  ],
  "tags": [
    { "name": "Discovery" },
    { "name": "Connectors" },
    { "name": "Properties" },
    { "name": "Status" },
    { "name": "Report" }
  ],
  "components": {
    "securitySchemes": {
      "ApiKeyHeader": {
        "type": "apiKey",
        "in": "header",
        "name": "Key",
        "description": "ImmoWP API key"
      },
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Same API key as Bearer token"
      },
      "XImmoWPKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-ImmoWP-Key"
      }
    },
    "parameters": {
      "crm": {
        "name": "crm",
        "in": "query",
        "required": true,
        "schema": { "type": "string", "pattern": "^[a-zA-Z0-9_-]+$" },
        "description": "Connector code (apimo, hektor, ubiflow, …)"
      },
      "client": {
        "name": "client",
        "in": "query",
        "required": true,
        "schema": { "type": "string", "pattern": "^[a-zA-Z0-9_-]+$" },
        "description": "Client slug"
      },
      "page": {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": { "type": "integer", "minimum": 1, "default": 1 }
      },
      "per_page": {
        "name": "per_page",
        "in": "query",
        "required": false,
        "schema": { "type": "integer", "minimum": 1, "maximum": 200, "default": 50 }
      },
      "propertyId": {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": { "type": "string" },
        "description": "affId or affNum"
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": ["status", "code", "message", "timestamp", "request_id"],
        "properties": {
          "status": { "type": "string", "const": "error" },
          "code": {
            "type": "string",
            "enum": [
              "BAD_REQUEST",
              "AUTH_FAILED",
              "FORBIDDEN",
              "NOT_FOUND",
              "METHOD_NOT_ALLOWED",
              "INTERNAL_ERROR"
            ]
          },
          "message": { "type": "string" },
          "timestamp": { "type": "string", "format": "date-time" },
          "request_id": { "type": "string" },
          "detail": { "type": "object", "additionalProperties": true }
        }
      },
      "Property": {
        "type": "object",
        "description": "Normalized listing (French camelCase fields)",
        "properties": {
          "affId": { "type": "string" },
          "affNum": { "type": "string" },
          "passerelleName": { "type": "string" },
          "intitule": { "type": "string" },
          "commentaires": { "type": "string" },
          "typeTransaction": { "type": "string" },
          "typeCode": { "type": "string" },
          "prix": { "type": ["string", "number"] },
          "prixCurrency": { "type": "string" },
          "loyer": { "type": ["string", "number"] },
          "surfaceHabitable": { "type": ["string", "number"] },
          "nbrePieces": { "type": ["string", "number"] },
          "nbreChambres": { "type": ["string", "number"] },
          "ville": { "type": "string" },
          "codePostal": { "type": "string" },
          "photos": {
            "type": "array",
            "items": { "type": ["string", "object"] }
          },
          "agenceNom": { "type": "string" },
          "negoEmail": { "type": "string" }
        },
        "additionalProperties": true
      },
      "Connector": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "label": { "type": "string" },
          "type": { "type": "string", "enum": ["api", "zip", "xml", "custom", "unknown"] },
          "notes": { "type": "string" }
        }
      },
      "StatusData": {
        "type": "object",
        "properties": {
          "crm": { "type": "string" },
          "client": { "type": "string" },
          "active": { "type": "boolean" },
          "contract_end": { "type": ["string", "null"] },
          "wordpress_url": { "type": ["string", "null"] },
          "last_update_status": { "type": ["string", "null"] },
          "last_update_count": { "type": ["integer", "null"] },
          "last_update_message": { "type": ["string", "null"] },
          "last_update_timestamp": { "type": ["string", "null"] },
          "connector": { "$ref": "#/components/schemas/Connector" }
        }
      },
      "ReportRequest": {
        "type": "object",
        "required": ["crm", "client", "status"],
        "properties": {
          "key": { "type": "string" },
          "api_key": { "type": "string" },
          "crm": { "type": "string" },
          "client": { "type": "string" },
          "status": { "type": "string", "enum": ["success", "error"] },
          "count": { "type": "integer", "minimum": 0 },
          "message": { "type": "string" },
          "site_url": { "type": "string", "format": "uri" },
          "wordpress_url": { "type": "string", "format": "uri" }
        }
      }
    }
  },
  "security": [{ "ApiKeyHeader": [] }, { "BearerAuth": [] }, { "XImmoWPKey": [] }],
  "paths": {
    "/v1": {
      "get": {
        "tags": ["Discovery"],
        "summary": "API discovery",
        "security": [],
        "responses": {
          "200": {
            "description": "Discovery document",
            "content": {
              "application/json": {
                "schema": { "type": "object", "additionalProperties": true }
              }
            }
          }
        }
      }
    },
    "/v1/connectors": {
      "get": {
        "tags": ["Connectors"],
        "summary": "List CRM connectors",
        "security": [],
        "responses": {
          "200": {
            "description": "Connector list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": { "type": "string" },
                    "data": {
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/Connector" }
                    },
                    "count": { "type": "integer" },
                    "request_id": { "type": "string" }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/status": {
      "get": {
        "tags": ["Status"],
        "summary": "Passerelle status",
        "parameters": [
          { "$ref": "#/components/parameters/crm" },
          { "$ref": "#/components/parameters/client" }
        ],
        "responses": {
          "200": {
            "description": "Status",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": { "type": "string" },
                    "data": { "$ref": "#/components/schemas/StatusData" },
                    "request_id": { "type": "string" }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Auth failed",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          },
          "403": {
            "description": "Disabled",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          }
        }
      }
    },
    "/v1/properties": {
      "get": {
        "tags": ["Properties"],
        "summary": "List properties (paginated)",
        "parameters": [
          { "$ref": "#/components/parameters/crm" },
          { "$ref": "#/components/parameters/client" },
          { "$ref": "#/components/parameters/page" },
          { "$ref": "#/components/parameters/per_page" }
        ],
        "responses": {
          "200": {
            "description": "Property page",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": { "type": "string" },
                    "data": {
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/Property" }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "page": { "type": "integer" },
                        "per_page": { "type": "integer" },
                        "total": { "type": "integer" },
                        "total_pages": { "type": "integer" },
                        "crm": { "type": "string" },
                        "client": { "type": "string" }
                      }
                    },
                    "request_id": { "type": "string" }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Auth failed",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          }
        }
      }
    },
    "/v1/properties/{id}": {
      "get": {
        "tags": ["Properties"],
        "summary": "Get property by affId or affNum",
        "parameters": [
          { "$ref": "#/components/parameters/propertyId" },
          { "$ref": "#/components/parameters/crm" },
          { "$ref": "#/components/parameters/client" }
        ],
        "responses": {
          "200": {
            "description": "Property",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": { "type": "string" },
                    "data": { "$ref": "#/components/schemas/Property" },
                    "request_id": { "type": "string" }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          }
        }
      }
    },
    "/v1/report": {
      "post": {
        "tags": ["Report"],
        "summary": "Report import result",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/ReportRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Report saved",
            "content": {
              "application/json": {
                "schema": { "type": "object", "additionalProperties": true }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          },
          "401": {
            "description": "Auth failed",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          }
        }
      }
    }
  }
}
