{
  "openapi": "3.0.0",
  "info": {
    "title": "Propertybase API Suite",
    "description": "Comprehensive API documentation for Propertybase integrations. Four core APIs work together: (1) Manda Middleware converts and delivers listings to property portals via API/FTP/Pickup; (2) Propertybase Ingestion API (PBPD) enables bulk object creation from external sources; (3) WebListings Query API (PBSE) retrieves live listing data for website display with search/filter/sort; (4) WebToProspect REST API (PBSE) captures leads from website forms with duplicate detection. All APIs support Bearer token and API key authentication.",
    "version": "1.0.0",
    "license": {
      "name": "Propertybase"
    },
    "contact": {
      "name": "Propertybase Support",
      "email": "support@propertybase.com"
    }
  },
  "servers": [
    {
      "url": "https://yourendpoint",
      "description": "Your Propertybase webservice endpoint (Setup > Sites > Custom URLs)"
    },
    {
      "url": "https://pb-integrations-api-staging.herokuapp.com",
      "description": "Propertybase Ingestion API (staging)"
    },
    {
      "url": "https://yoursitename.secure.force.com",
      "description": "WebToProspect endpoint"
    }
  ],
  "paths": {
    "/manda/portal-listings": {
      "get": {
        "tags": ["Manda Middleware"],
        "summary": "Get Portal Listing status",
        "description": "Query Portal Listing records to check publication status, delivery results, and error details. Portal Listings track the publishing workflow from Propertybase through Manda to destination portals.",
        "operationId": "getPortalListings",
        "parameters": [
          {
            "name": "listing_id",
            "in": "query",
            "description": "Filter by Listing ID",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "portal_id",
            "in": "query",
            "description": "Filter by Portal ID",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Filter by status (Published, Failed, Pending, Withdrawn)",
            "schema": {
              "type": "string",
              "enum": ["Published", "Failed", "Pending", "Withdrawn"]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Portal Listing records",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/PortalListing"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/pba__WebserviceListingsQuery": {
      "get": {
        "tags": ["WebListings Query API"],
        "summary": "Query Propertybase listings",
        "description": "Retrieve listings from Propertybase with filtering, sorting, and pagination. Returns XML or JSON.",
        "operationId": "queryListings",
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "description": "Your webserviceWebListings_token",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "fields",
            "in": "query",
            "description": "Semicolon-separated field API names (e.g., name;pba__ListingPrice_pb__c;pba__Bedrooms_pb__c)",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "itemsperpage",
            "in": "query",
            "description": "Number of results per page (default: 20, max: 1000)",
            "schema": {
              "type": "integer",
              "default": 20
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "Page number (0-indexed)",
            "schema": {
              "type": "integer",
              "default": 0
            }
          },
          {
            "name": "orderby",
            "in": "query",
            "description": "Sort field and direction (e.g., pba__ListingPrice_pb__c;ASC)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "getimages",
            "in": "query",
            "description": "Include image URLs",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "getvideos",
            "in": "query",
            "description": "Include video URLs",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "getdocuments",
            "in": "query",
            "description": "Include document URLs",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "debugmode",
            "in": "query",
            "description": "Include debug messages in response",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful query response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebListingsResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid query parameters"
          },
          "401": {
            "description": "Invalid or missing token"
          }
        }
      }
    },
    "/services/apexrest/pba/webtoprospect/v1/": {
      "post": {
        "tags": ["WebToProspect REST API"],
        "summary": "Create contact and inquiry",
        "description": "Submit website leads to create contacts and inquiries in Propertybase. Supports duplicate detection.",
        "operationId": "submitProspect",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebToProspectRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Prospect created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebToProspectResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request or missing required fields"
          },
          "401": {
            "description": "Authentication failed"
          }
        }
      }
    },
    "/api/v1/messages/{orgid}": {
      "post": {
        "tags": ["Propertybase Ingestion API (PBPD)"],
        "summary": "Create bulk objects",
        "description": "Write-only API for creating bulk objects (Leads, Contacts, Inquiries, etc.) in Propertybase",
        "operationId": "bulkCreate",
        "parameters": [
          {
            "name": "orgid",
            "in": "path",
            "description": "Your Propertybase organization ID",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IngestionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Objects created successfully"
          },
          "400": {
            "description": "Invalid object or field"
          },
          "401": {
            "description": "Invalid API key"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "WebListingsResponse": {
        "type": "object",
        "properties": {
          "page": {
            "type": "integer",
            "description": "Current page number (0-indexed)"
          },
          "listingsPerPage": {
            "type": "integer",
            "description": "Number of listings per page"
          },
          "numberOfListings": {
            "type": "integer",
            "description": "Total listings matching filter"
          },
          "fatalError": {
            "type": "boolean",
            "description": "Whether a fatal error occurred"
          },
          "errorMessages": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Any error messages"
          },
          "debugMessages": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Debug messages (if debugmode=true)"
          },
          "listings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Listing"
            },
            "description": "Array of matching listings"
          }
        }
      },
      "Listing": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "description": "Listing field data (fields vary by request)",
            "properties": {
              "id": {
                "type": "string",
                "description": "Listing record ID"
              },
              "name": {
                "type": "string",
                "description": "Listing name/address"
              },
              "pba__ListingPrice_pb__c": {
                "type": "number",
                "description": "Listing price"
              },
              "pba__Bedrooms_pb__c": {
                "type": "number",
                "description": "Number of bedrooms"
              },
              "pba__FullBathrooms_pb__c": {
                "type": "number",
                "description": "Number of bathrooms"
              }
            }
          },
          "media": {
            "type": "object",
            "properties": {
              "images": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/MediaItem"
                }
              },
              "videos": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/MediaItem"
                }
              },
              "documents": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/MediaItem"
                }
              }
            }
          }
        }
      },
      "MediaItem": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string"
          },
          "filename": {
            "type": "string"
          },
          "tags": {
            "type": "string"
          },
          "mimetype": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "baseurl": {
            "type": "string",
            "format": "uri"
          },
          "external": {
            "type": "boolean",
            "description": "True if hosted externally (e.g., YouTube)"
          }
        }
      },
      "WebToProspectRequest": {
        "type": "object",
        "required": ["prospect"],
        "properties": {
          "prospect": {
            "type": "object",
            "required": ["contact"],
            "properties": {
              "token": {
                "type": "string",
                "description": "Required for anonymous calls only"
              },
              "contact": {
                "type": "object",
                "required": ["LastName"],
                "properties": {
                  "FirstName": {
                    "type": "string"
                  },
                  "LastName": {
                    "type": "string"
                  },
                  "Email": {
                    "type": "string",
                    "format": "email"
                  },
                  "Phone": {
                    "type": "string"
                  },
                  "MobilePhone": {
                    "type": "string"
                  },
                  "OwnerId": {
                    "type": "string",
                    "description": "Salesforce User ID to assign record"
                  }
                }
              },
              "request": {
                "type": "object",
                "description": "Inquiry/search criteria data",
                "properties": {
                  "pba__Bedrooms_pb_min__c": {
                    "type": "number"
                  },
                  "pba__Bedrooms_pb_max__c": {
                    "type": "number"
                  },
                  "pba__FullBathrooms_pb_min__c": {
                    "type": "number"
                  },
                  "pba__FullBathrooms_pb_max__c": {
                    "type": "number"
                  }
                }
              },
              "favoriteListings": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Array of listing IDs to link to inquiry"
              },
              "contactFields": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Contact fields to return in response"
              },
              "requestFields": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Inquiry fields to return in response"
              },
              "ownerFields": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Owner user fields to return in response"
              }
            }
          }
        }
      },
      "WebToProspectResponse": {
        "type": "object",
        "properties": {
          "errorMessage": {
            "type": "string",
            "nullable": true,
            "description": "Error message or null if successful"
          },
          "contact": {
            "type": "object",
            "description": "Returned contact data"
          },
          "request": {
            "type": "object",
            "description": "Returned inquiry data"
          },
          "owner": {
            "type": "object",
            "description": "Returned owner user data"
          }
        }
      },
      "IngestionRequest": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": ["Lead", "ContactForm", "SavedSearch", "PropertyView", "Inquiry", "EmailFriend", "FavoriteProp", "PropertyShowing", "PropertyNote"]
          },
          "records": {
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        }
      },
      "PortalListing": {
        "type": "object",
        "description": "Manda Portal Listing record tracking publication status and delivery results",
        "properties": {
          "Id": {
            "type": "string",
            "description": "Portal Listing record ID (pba__PortalListing__c)"
          },
          "pba__Listing__c": {
            "type": "string",
            "description": "Reference to Listing record being published"
          },
          "pba__Portal__c": {
            "type": "string",
            "description": "Reference to Portal configuration (defines delivery method, credentials, endpoint)"
          },
          "pba__Status__c": {
            "type": "string",
            "enum": ["Published", "Failed", "Pending", "Withdrawn"],
            "description": "Current publication status"
          },
          "pba__ErrorMessage__c": {
            "type": "string",
            "description": "Detailed error message if rendering or delivery failed"
          },
          "pba__DeliveryMethod__c": {
            "type": "string",
            "enum": ["API", "FTP", "Pickup"],
            "description": "How listing is delivered to portal"
          },
          "pba__LastModifiedDate": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp of last status update"
          },
          "pba__RenderedOutput__c": {
            "type": "string",
            "description": "Format of rendered output (XML, JSON, or CSV)"
          }
        }
      },
      "MandaPublishingWorkflow": {
        "type": "object",
        "description": "Manda Publishing Workflow - the 7-step process for listing publication",
        "properties": {
          "step_1_publish": {
            "type": "string",
            "description": "User publishes listing to portal in Propertybase UI"
          },
          "step_2_send_to_manda": {
            "type": "string",
            "description": "Propertybase sends listing data and portal settings to Manda middleware"
          },
          "step_3_render": {
            "type": "string",
            "description": "Manda converts listing to portal-required format (XML, JSON, or CSV). Missing fields and unsupported picklist values detected here."
          },
          "step_4_store_output": {
            "type": "string",
            "description": "Rendered feed is saved in the feed store for delivery or portal pickup"
          },
          "step_5_status_writeback": {
            "type": "string",
            "description": "Manda writes result (success/validation error/delivery error) to Portal Listing record (pba__PortalListing__c)"
          },
          "step_6_deliver": {
            "type": "string",
            "description": "Manda delivers listing by API push (real-time), scheduled FTP upload, or makes available for Pickup"
          },
          "step_7_delete_handling": {
            "type": "string",
            "description": "Listing removal sends delete or withdrawn instruction to portal; may process even for inactive portals"
          }
        }
      },
      "MandaPortalConfiguration": {
        "type": "object",
        "description": "Configuration required for Manda to publish to a portal",
        "required": ["delivery_method", "generator"],
        "properties": {
          "delivery_method": {
            "type": "string",
            "enum": ["API", "FTP", "Pickup"],
            "description": "How Manda delivers the listing feed"
          },
          "api_endpoint": {
            "type": "string",
            "format": "uri",
            "description": "Portal API endpoint (required for API delivery)"
          },
          "api_credentials": {
            "type": "object",
            "description": "Authentication for API delivery",
            "properties": {
              "api_key": {
                "type": "string"
              },
              "bearer_token": {
                "type": "string"
              }
            }
          },
          "ftp_host": {
            "type": "string",
            "description": "FTP server hostname (required for FTP delivery)"
          },
          "ftp_username": {
            "type": "string",
            "description": "FTP authentication username"
          },
          "ftp_password": {
            "type": "string",
            "description": "FTP authentication password"
          },
          "ftp_path": {
            "type": "string",
            "description": "Directory path on FTP server for file upload"
          },
          "ftp_schedule": {
            "type": "string",
            "description": "Scheduled upload frequency (e.g., daily, hourly)"
          },
          "pickup_url": {
            "type": "string",
            "format": "uri",
            "description": "URL where portal can download feed (required for Pickup delivery)"
          },
          "generator": {
            "type": "string",
            "description": "Portal-specific renderer (e.g., 'MLS XML Renderer', 'Zillow JSON Renderer')"
          },
          "output_format": {
            "type": "string",
            "enum": ["XML", "JSON", "CSV"],
            "description": "Portal-required output format"
          },
          "field_mapping": {
            "type": "object",
            "description": "Maps Propertybase field names to portal field names"
          }
        }
      },
      "MandaError": {
        "type": "object",
        "description": "Manda rendering or delivery error",
        "properties": {
          "error_code": {
            "type": "string",
            "enum": ["[Listing invalid]", "[FailedMapping]", "No FTP credentials", "[NoEndpoint]", "[InvalidPicklistValue]"]
          },
          "error_message": {
            "type": "string",
            "description": "Detailed error description"
          },
          "field_name": {
            "type": "string",
            "description": "If applicable, the field causing the error"
          },
          "solution": {
            "type": "string",
            "description": "Recommended corrective action"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "description": "When error occurred"
          },
          "listing_id": {
            "type": "string",
            "description": "ID of listing with error"
          },
          "portal_id": {
            "type": "string",
            "description": "ID of portal configuration with error"
          }
        }
      }
    },
    "securitySchemes": {
      "BearerToken": {
        "type": "http",
        "scheme": "bearer",
        "description": "Bearer token provided by Propertybase CS team"
      },
      "ApiKey": {
        "type": "apiKey",
        "in": "query",
        "name": "token",
        "description": "API token as query parameter"
      }
    }
  },
  "security": [
    {
      "BearerToken": []
    },
    {
      "ApiKey": []
    }
  ],
  "tags": [
    {
      "name": "WebListings Query API",
      "description": "Query and retrieve Propertybase listings for display on websites"
    },
    {
      "name": "WebToProspect REST API",
      "description": "Create leads and inquiries from website forms with duplicate detection"
    },
    {
      "name": "Propertybase Ingestion API (PBPD)",
      "description": "Write-only API for bulk object creation"
    },
    {
      "name": "Manda Middleware",
      "description": "Manda is the internal middleware layer that automates portal publishing. It converts Propertybase listings into portal-specific formats (XML, JSON, CSV), handles field mapping and validation, and delivers via API (real-time push), FTP (scheduled upload), or Pickup (portal-initiated download). Manda tracks all publication status in Portal Listing records (pba__PortalListing__c). The 7-step publishing workflow: (1) User publishes in Propertybase, (2) Data sent to Manda, (3) Rendering to portal format, (4) Output stored in feed store, (5) Status written to Portal Listing, (6) Delivery via configured method, (7) Delete/withdrawn handling. Common errors include missing required fields, unsupported picklist values, broken field mappings, and missing FTP credentials."
    }
  ]
}
