{
  "openapi": "3.0.3",
  "info": {
    "title": "Spacyn Host Public API",
    "version": "1.0.0",
    "description": "REST API untuk integrasi host Spacyn (PMS, calendar, automation)."
  },
  "servers": [
    {
      "url": "https://{project}.supabase.co/functions/v1",
      "variables": {
        "project": {
          "default": "your-project-ref"
        }
      }
    }
  ],
  "security": [
    {
      "ApiKeyAuth": []
    }
  ],
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "API Key"
      }
    },
    "schemas": {
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "success": { "type": "boolean", "example": false },
          "error": {
            "type": "object",
            "properties": {
              "code": { "type": "string", "example": "INVALID_API_KEY" },
              "message": { "type": "string" },
              "http_status": { "type": "integer", "example": 401 }
            }
          }
        }
      },
      "Space": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "title": { "type": "string" },
          "category_slug": { "type": "string" },
          "description": { "type": "string", "nullable": true },
          "address": { "type": "string" },
          "area": { "type": "string" },
          "price_per_hour": { "type": "number" },
          "capacity": { "type": "integer", "nullable": true },
          "operating_hours": {
            "type": "object",
            "properties": {
              "start_hour": { "type": "integer" },
              "end_hour": { "type": "integer" }
            }
          },
          "rating": { "type": "number" },
          "review_count": { "type": "integer" },
          "is_active": { "type": "boolean" },
          "amenities": {
            "type": "array",
            "items": { "type": "string" }
          },
          "photo_urls": {
            "type": "array",
            "items": { "type": "string" }
          }
        }
      },
      "AvailabilitySlot": {
        "type": "object",
        "properties": {
          "hour": { "type": "integer", "minimum": 0, "maximum": 23 },
          "available": { "type": "boolean" },
          "block_reason": {
            "type": "string",
            "nullable": true,
            "enum": ["booked", "external_block", "host_block", null]
          }
        }
      }
    }
  },
  "paths": {
    "/api-listings/api/v1/spaces": {
      "get": {
        "summary": "List all host spaces",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "data": {
                    "spaces": []
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "source": "curl -H \"Authorization: Bearer <API_KEY>\" https://<project>.supabase.co/functions/v1/api-listings/api/v1/spaces"
          },
          {
            "lang": "JavaScript",
            "source": "await fetch(`${base}/api-listings/api/v1/spaces`, { headers: { Authorization: `Bearer ${apiKey}` } });"
          }
        ]
      }
    },
    "/api-listings/api/v1/spaces/{space_id}": {
      "get": {
        "summary": "Get space detail",
        "parameters": [
          {
            "in": "path",
            "name": "space_id",
            "required": true,
            "schema": { "type": "string", "format": "uuid" }
          }
        ],
        "responses": {
          "200": { "description": "Success" },
          "404": { "description": "Not found" }
        }
      }
    },
    "/api-availability/api/v1/spaces/{space_id}/availability": {
      "get": {
        "summary": "Get 24-hour availability",
        "parameters": [
          {
            "in": "path",
            "name": "space_id",
            "required": true,
            "schema": { "type": "string", "format": "uuid" }
          },
          {
            "in": "query",
            "name": "date",
            "required": true,
            "schema": { "type": "string", "example": "2026-03-15" }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "data": {
                    "space_id": "uuid",
                    "date": "2026-03-15",
                    "slots": []
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api-bookings/api/v1/bookings": {
      "get": {
        "summary": "List host bookings",
        "parameters": [
          { "in": "query", "name": "space_id", "schema": { "type": "string", "format": "uuid" } },
          { "in": "query", "name": "status", "schema": { "type": "string" } },
          { "in": "query", "name": "from", "schema": { "type": "string" } },
          { "in": "query", "name": "to", "schema": { "type": "string" } },
          { "in": "query", "name": "limit", "schema": { "type": "integer", "default": 50 } },
          { "in": "query", "name": "offset", "schema": { "type": "integer", "default": 0 } }
        ],
        "responses": {
          "200": { "description": "Success" }
        }
      }
    },
    "/api-create-booking/api/v1/bookings": {
      "post": {
        "summary": "Create booking via public API",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "example": {
                "space_id": "uuid",
                "date": "2026-03-20",
                "start_hour": 14,
                "end_hour": 16,
                "guest_email": "guest@example.com",
                "guest_name": "Guest Name",
                "guest_phone": "08123456789",
                "settlement_mode": "host_settled",
                "idempotency_key": "booking-20260320-001"
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Success" },
          "409": { "description": "BOOKING_CONFLICT" },
          "422": { "description": "BOOKING_INVALID_SETTLEMENT_MODE | BOOKING_VALUE_EXCEEDED" },
          "429": { "description": "GUEST_BOOKING_VELOCITY | RATE_LIMIT_EXCEEDED" }
        }
      }
    },
    "/api-booking-detail/api/v1/bookings/{booking_id}": {
      "get": {
        "summary": "Get booking detail by booking_id",
        "parameters": [
          {
            "in": "path",
            "name": "booking_id",
            "required": true,
            "schema": { "type": "string", "format": "uuid" }
          }
        ],
        "responses": {
          "200": { "description": "Success" },
          "404": { "description": "Not found" }
        }
      }
    },
    "/api-cancel-booking/api/v1/bookings/{booking_id}/cancel": {
      "post": {
        "summary": "Cancel booking via API",
        "parameters": [
          {
            "in": "path",
            "name": "booking_id",
            "required": true,
            "schema": { "type": "string", "format": "uuid" }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "example": {
                "reason": "Guest requested cancellation"
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Success" },
          "422": { "description": "BOOKING_CANCELLATION_BLOCKED | VALIDATION_ERROR" }
        }
      }
    },
    "/api-settlement-report/api/v1/settlement/report": {
      "get": {
        "summary": "Get host settlement report for API bookings",
        "parameters": [
          {
            "in": "query",
            "name": "month",
            "required": true,
            "schema": { "type": "string", "example": "2026-03" }
          }
        ],
        "responses": {
          "200": { "description": "Success" }
        }
      }
    },
    "/api-earnings/api/v1/earnings": {
      "get": {
        "summary": "Get host earnings summary",
        "responses": {
          "200": { "description": "Success" }
        }
      }
    },
    "/api-blocks/api/v1/spaces/{space_id}/blocks": {
      "post": {
        "summary": "Create host blocks",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "example": {
                "space_id": "uuid",
                "date": "2026-03-15",
                "start_hour": 9,
                "end_hour": 12,
                "reason": "maintenance"
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Success" },
          "409": { "description": "BLOCK_SLOT_OCCUPIED" }
        }
      },
      "delete": {
        "summary": "Delete host blocks",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "example": {
                "space_id": "uuid",
                "date": "2026-03-15",
                "start_hour": 9,
                "end_hour": 12
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Success" }
        }
      }
    },
    "/api-listing-update/api/v1/spaces/{space_id}": {
      "patch": {
        "summary": "Update listing fields",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "example": {
                "space_id": "uuid",
                "title": "Updated title",
                "price": 200000,
                "is_active": true
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Success" }
        }
      }
    },
    "/api-webhooks/api/v1/webhooks": {
      "get": { "summary": "List webhooks", "responses": { "200": { "description": "Success" } } },
      "post": {
        "summary": "Create webhook subscription",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "example": {
                "url": "https://your-app.com/webhooks/spacyn",
                "events": ["booking.created", "availability.changed"],
                "description": "Production endpoint"
              }
            }
          }
        },
        "responses": {
          "201": { "description": "Created" }
        }
      }
    },
    "/api-webhooks/api/v1/webhooks/{id}": {
      "patch": { "summary": "Update webhook", "responses": { "200": { "description": "Success" } } },
      "delete": { "summary": "Delete webhook", "responses": { "200": { "description": "Success" } } }
    },
    "/api-ical-feed": {
      "get": {
        "summary": "Download iCal feed",
        "security": [],
        "parameters": [
          { "in": "query", "name": "space_id", "required": true, "schema": { "type": "string", "format": "uuid" } },
          { "in": "query", "name": "token", "required": true, "schema": { "type": "string", "format": "uuid" } }
        ],
        "responses": {
          "200": { "description": "text/calendar" },
          "401": { "description": "Invalid token" }
        }
      }
    },
    "/api-openapi": {
      "get": {
        "summary": "Get OpenAPI spec JSON",
        "security": [],
        "responses": {
          "200": { "description": "Success" }
        }
      }
    }
  },
  "x-errors": {
    "INVALID_API_KEY": "401",
    "API_KEY_REVOKED": "401",
    "RATE_LIMIT_EXCEEDED": "429",
    "BLOCK_SLOT_OCCUPIED": "409",
    "BOOKING_CONFLICT": "409",
    "BOOKING_INVALID_SETTLEMENT_MODE": "422",
    "BOOKING_CANCELLATION_BLOCKED": "422",
    "GUEST_BOOKING_VELOCITY": "429",
    "SELF_BOOKING_BLOCKED": "403",
    "BOOKING_VALUE_EXCEEDED": "422"
  },
  "x-rate-limits": {
    "production": "100 requests/minute per API key",
    "sandbox": "20 requests/minute per API key"
  },
  "x-webhook-events": [
    "booking.created",
    "booking.cancelled",
    "booking.completed",
    "availability.changed",
    "listing.updated",
    "payment.confirmed"
  ]
}
