{
  "openapi": "3.1.0",
  "info": {
    "title": "Showami",
    "description": "The Showami API for creating, accepting, and updating showings and rentals.\n\nSee the [API Changelog](/api-changelog) for what changed in each release.\n\n## API key access levels\n\nEvery request must include an `X-Api-Key` header. Keys are issued at one of two access\nlevels:\n\n- **Full access** — can read and modify resources via any HTTP method.\n- **Read-only** — restricted to `GET`, `HEAD`, and `OPTIONS` requests. Any request using\n  another method is rejected with `403 Forbidden` and the body\n  `{ \"message\": \"Read-only API keys cannot modify resources.\" }`. Use a read-only key\n  for integrations that only need to pull data (reporting, dashboards, audits). The\n  sign-in endpoints (`POST /api/v1/users/tokens` and `POST /users/sign_in`) are\n  allowlisted so the key bearer can still exchange credentials for a user token.\n\n## Idempotent creation\n\nThe create endpoints (`POST /api/v1/showings`, `POST /api/v1/tasks`,\n`POST /api/v1/rentals` and `POST /api/v1/consumers/showings`) accept an optional\n`Idempotency-Key` header, so a request can be retried safely when its response\nnever arrives (a timeout or dropped connection) without risking a duplicate booking.\n\n- Use a unique value per showing you intend to create, such as a UUID or your own\n  booking id, and send the same value on every retry of that request. Keys are\n  scoped to the authenticated user (for consumer showings, to the consumer) and up\n  to 255 characters.\n- Once the original request has succeeded, a retry with the same key creates nothing\n  and returns `200` with the original showing(s), in their current state, plus an\n  `Idempotent-Replayed: true` response header.\n- A retry must send the same request body as the original (the order of JSON keys\n  doesn't matter). Reusing a key with a different body returns `422` with\n  `{ \"message\": \"This Idempotency-Key was already used with a different request. Use a new key for a new request.\" }`\n  and creates nothing.\n- While the original is still being processed, a retry returns `409 Conflict`; wait\n  and retry again with the same key.\n- If the original failed (any non-`200` response), nothing was booked and the key is\n  released, so a retry with the same key is processed as a new request.\n\n## Rate limits\n\nRequests are rate limited to keep the API responsive for every integration.\n\n| Scope | Limit |\n| --- | --- |\n| All API requests, per client IP address | 50 requests per 10 seconds |\n| `POST /users/sign_in`, per IP address and per email | 5 attempts per 20 seconds |\n\nA request over the limit gets `429 Too Many Requests`. It's rejected before it\nreaches the API, so nothing was created or changed and the request is safe to retry.\n\n- Check the status code, not the body. A `429` from the general limit comes from our\n  edge network, so its body may be HTML rather than JSON.\n- If the response has a `Retry-After` header, wait that many seconds before retrying.\n  Otherwise wait at least 10 seconds, then back off exponentially (10s, 20s, 40s…)\n  with some random jitter. Retrying right away keeps the window full and extends the\n  block.\n- Send the same `Idempotency-Key` when you retry a create (see \"Idempotent creation\").\n- Spread bulk work out: a steady 5 requests per second stays under the limit, while a\n  burst of 50 at once uses up the whole window. Use webhooks rather than polling\n  where you can.\n\nThese limits may change. We'll give integration partners notice before lowering them.\nIf your integration needs a higher limit, contact us.\n",
    "version": "1.0",
    "license": {
      "name": "Showami Terms of Service",
      "url": "https://www.showami.com/terms"
    }
  },
  "servers": [
    {
      "url": "/"
    }
  ],
  "security": [
    {
      "APIKeyHeader": [],
      "UserEmailHeader": [],
      "UserTokenHeader": []
    },
    {
      "APIKeyHeader": [],
      "oAuth2Password": []
    }
  ],
  "tags": [
    {
      "name": "Authentication",
      "description": "Authenticate with Showami"
    },
    {
      "name": "Showings",
      "description": "API endpoints related to Showings"
    },
    {
      "name": "Messages",
      "description": "API endpoints related to Messages"
    },
    {
      "name": "Tasks",
      "description": "API endpoints related to Tasks"
    },
    {
      "name": "Rentals",
      "description": "API endpoints related to Rentals"
    },
    {
      "name": "Property Data Collection",
      "description": "API endpoints related to Property Data Collection appointments. These use the same underlying `/showings` endpoint as a standard showing, but with `showing_type` set to `property_data_collection`. They are documented separately for clarity."
    },
    {
      "name": "Users",
      "description": "API endpoints related to Users"
    },
    {
      "name": "Consumers",
      "description": "API endpoints related to Consumers"
    },
    {
      "name": "Referrals",
      "description": "API endpoints related to Referrals"
    },
    {
      "name": "Price Suggestions",
      "description": "API Endpoints related to Showing Price Suggestions"
    },
    {
      "name": "Reports",
      "description": "API endpoints to list and download Organization reports"
    },
    {
      "name": "Webhooks",
      "description": "Showami webhooks"
    }
  ],
  "paths": {
    "/api/v1/showings": {
      "get": {
        "summary": "Accepted Showings",
        "description": "Get a list of all Showings where the authenticated user is the Showing Agent.",
        "tags": [
          "Showings"
        ],
        "parameters": [
          {
            "name": "exclude_fields",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Comma separated list of fields to leave out of the response, for\nclients that don't need them. Currently only `avatar_base64` (on the\n`user` and `showing_agent` profiles) can be excluded; any other field\nname is ignored. Omitting it returns the full payload.\n",
            "example": "avatar_base64"
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ShowingResponse"
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create Showing(s)",
        "description": "Create a new Showing or multiple Showings.\n\nTo create a PDC (Property Data Collection) appointment, send\n`showing_type` set to `property_data_collection` with the\n`PropertyDataCollectionRequestWrapper` body shown below.\n",
        "tags": [
          "Showings",
          "Property Data Collection"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKeyHeader"
          }
        ],
        "operationId": "create_showing",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/ShowingRequestWrapper"
                  },
                  {
                    "$ref": "#/components/schemas/PropertyDataCollectionRequestWrapper"
                  }
                ]
              },
              "examples": {
                "property_data_collection": {
                  "summary": "Property Data Collection",
                  "value": {
                    "showing_request": {
                      "showing_type": "property_data_collection",
                      "price": 50,
                      "access_information": "Access information for the showing...",
                      "notes": "Private notes...",
                      "public_notes": "Public notes...",
                      "external_app_url": "https://partner.example.com/showings/abc-123",
                      "showing_request_properties_attributes": {
                        "0": {
                          "showing_at(1i)": "2026",
                          "showing_at(2i)": "04",
                          "showing_at(3i)": "16",
                          "showing_at(4i)": "14",
                          "showing_at(5i)": "30",
                          "duration": 0.5,
                          "line1": "123 Main St",
                          "city": "Denver",
                          "state": "CO",
                          "zip": "80202",
                          "external_id": "ext-id-abc1234"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "If successful, returns a JSON object containing a message and the created showing(s) in `body`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShowingCreateResponse"
                },
                "examples": {
                  "property_data_collection": {
                    "summary": "Property Data Collection",
                    "value": {
                      "message": "New property data collection successfully created.",
                      "body": [
                        {
                          "id": 1231,
                          "showing_request_id": 1257,
                          "showing_at": "2026-04-16T14:30:00.000-06:00",
                          "time_zone": "Mountain Time (US & Canada)",
                          "duration": 0.5,
                          "access_information": "Access information for the showing...",
                          "notes": "Private notes...",
                          "public_notes": "Public notes...",
                          "price": 50,
                          "payout": 32,
                          "charge_amount": 49,
                          "charge_details": [
                            {
                              "description": "Showing cost",
                              "amount": 5000
                            },
                            {
                              "description": "Platinum member discount",
                              "amount": -100
                            }
                          ],
                          "transfer_amount": 32,
                          "transfer_details": [
                            {
                              "description": "Showing payout",
                              "amount": 3200
                            }
                          ],
                          "paid_group_amount": 32,
                          "status": "unassigned",
                          "showing_type": "property_data_collection",
                          "external_id": "ext-id-abc1234",
                          "external_app_url": "https://partner.example.com/showings/abc-123",
                          "external_app_icon_path": "partners/app_icons/partner.png",
                          "standard_tz_identifier": "America/Denver",
                          "address": {
                            "id": 1490,
                            "line1": "123 Main St",
                            "city": "Denver",
                            "state": "CO",
                            "zip": "80202",
                            "latitude": 39.6403007,
                            "longitude": -106.3736102
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "A request with the same `Idempotency-Key` is still being processed. Retry shortly with the same key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "A request with this Idempotency-Key is still being processed. Retry shortly."
                }
              }
            }
          },
          "422": {
            "description": "Returned when the request fails validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "Price is not valid for the selected showing type"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/showings/{showing_id}": {
      "get": {
        "summary": "Accepted Showing by Id",
        "description": "Get the details of a showing where the user is the Showing Agent.",
        "tags": [
          "Showings"
        ],
        "parameters": [
          {
            "name": "showing_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "exclude_fields",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Comma separated list of fields to leave out of the response, for\nclients that don't need them. Currently only `avatar_base64` (on the\n`user` and `showing_agent` profiles) can be excluded; any other field\nname is ignored. Omitting it returns the full payload.\n",
            "example": "avatar_base64"
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShowingResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/showings/opportunities": {
      "get": {
        "summary": "Showing Opportunities",
        "description": "All Showing opportunities that match the Showing Agent preferences.",
        "tags": [
          "Showings"
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ShowingResponse"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/showings/requests": {
      "get": {
        "summary": "Showing Requests",
        "description": "Get a list of all requested showings of the authenticated user.\n\nThe response is a page of showings, ordered, filtered and paginated by the\nquery parameters below. Every parameter is optional; the ones listed here are\nthe only ones this endpoint reads, and anything else in the query string is\nignored.\n\n**Fetching a full history in bulk**\n\nFor bulk reads, page with `q[order_by]=showing_at&q[sort_direction]=asc` instead. That\nordering is stable — new rows land at the end rather than the front.\n\nCombine it with `q[showing_at_from]` and `q[showing_at_to]` to walk the history\nin bounded windows rather than re-reading it from the beginning as it grows.\n",
        "tags": [
          "Showings"
        ],
        "parameters": [
          {
            "name": "q[order_by]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "showing_at",
                "updated_at"
              ],
              "default": "showing_at"
            },
            "description": "Column to sort on. `showing_at` is when the showing is scheduled;\n`updated_at` is when the showing record last changed. Both are tie-broken\non the showing id, in the same direction, so paging is deterministic.\n",
            "example": "showing_at"
          },
          {
            "name": "q[sort_direction]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Direction for `q[order_by]`. Case insensitive. Use `asc` when paging\nthrough a large result set — see the endpoint description.\n",
            "example": "asc"
          },
          {
            "name": "q[showing_at_from]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Only return showings scheduled at or after this moment (inclusive). ISO 8601\ndate (`YYYY-MM-DD`) or timestamp (`YYYY-MM-DDTHH:MM:SSZ`). A value without a\nUTC offset — including a bare date, which means midnight — is read in the\nauthenticated user's profile time zone.\n",
            "example": "2026-01-01T00:00:00Z"
          },
          {
            "name": "q[showing_at_to]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Only return showings scheduled at or before this moment (inclusive). Same\nformats and time zone handling as `q[showing_at_from]`.\n",
            "example": "2026-02-01T00:00:00Z"
          },
          {
            "name": "q[statuses][]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "unassigned",
                "accepted",
                "completed",
                "canceled"
              ]
            },
            "description": "Only return showings in the given status. Repeat the parameter to filter on\nmore than one; the matches are OR'd together\n(`?q[statuses][]=accepted&q[statuses][]=completed`). Omitting it returns\nshowings in every status. Any value outside the listed set is ignored and\ndoes not narrow the results.\n",
            "example": "accepted"
          },
          {
            "name": "q[buyer_external_id]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Only return showings carrying this `buyer_external_id`, the identifier your\nsystem supplied when the showing was created. Surrounding whitespace is\nstripped; the comparison is otherwise exact.\n",
            "example": "buyer-1234"
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 1
            },
            "description": "1-based page number. A page past the end returns an empty array."
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 15
            },
            "description": "Number of showings per page. There is no enforced maximum, but responses are\nlarge (each showing embeds its agent profiles), so values above ~100 are slow\n— page through instead, and use `exclude_fields=avatar_base64` to drop the\nbulkiest field.\n"
          },
          {
            "name": "exclude_fields",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Comma separated list of fields to leave out of the response, for\nclients that don't need them. Currently only `avatar_base64` (on the\n`user` and `showing_agent` profiles) can be excluded; any other field\nname is ignored. Omitting it returns the full payload.\n",
            "example": "avatar_base64"
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "headers": {
              "X-Total-Entries": {
                "schema": {
                  "type": "integer"
                },
                "description": "Total showings matching the filters, across all pages."
              },
              "X-Total-Pages": {
                "schema": {
                  "type": "integer"
                },
                "description": "Total number of pages at the current `per_page`."
              },
              "X-Current-Page": {
                "schema": {
                  "type": "integer"
                },
                "description": "The page number in this response."
              },
              "X-Per-Page": {
                "schema": {
                  "type": "integer"
                },
                "description": "The page size applied to this response."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ShowingResponse"
                  }
                }
              }
            }
          },
          "400": {
            "description": "A sort or filter parameter could not be understood.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "q[order_by] must be one of showing_at, updated_at"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/showings/requests/{showing_request_id}": {
      "get": {
        "summary": "Showing Request by Id",
        "description": "Get the details of a showing request where the user is the Initiating Agent, including its showings.",
        "tags": [
          "Showings"
        ],
        "parameters": [
          {
            "name": "showing_request_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "exclude_fields",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Comma separated list of fields to leave out of the response, for\nclients that don't need them. Currently only `avatar_base64` (on the\nprofiles of the showings included in the response) can be excluded;\nany other field name is ignored. Omitting it returns the full payload.\n",
            "example": "avatar_base64"
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShowingRequestResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/showings/{showing_id}/tip": {
      "put": {
        "summary": "Add a Tip",
        "description": "Add (or change) a tip for the showing agent on a showing or Task list you requested. Tips are open only while the showing is in the `completed` status, which is the window between completion and the start of payment. For a Task list, completion is the moment its tasks are approved, so the window runs until `tip_window_ends_at` - 24 hours after the later of the approval and the scheduled end of the task window. The amount is a whole number of dollars and replaces any tip already recorded.",
        "tags": [
          "Showings"
        ],
        "operationId": "showing_tip",
        "parameters": [
          {
            "name": "showing_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "tip": {
                    "type": "integer",
                    "description": "The tip amount, in whole dollars. Must be positive.",
                    "example": 15
                  }
                },
                "required": [
                  "tip"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Response"
                },
                "example": {
                  "message": "Thank you. An extra $15 will be given to the showing agent less any transaction fees."
                }
              }
            }
          },
          "403": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "A tip can no longer be added to this showing."
                }
              }
            }
          },
          "422": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "Please enter a whole, positive dollar amount for the tip."
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/showings/{showing_id}/buyers_agent_cancel": {
      "put": {
        "summary": "Cancel Showing",
        "description": "You may cancel an existing showing for which you have initiated.",
        "tags": [
          "Showings"
        ],
        "operationId": "showing_buyers_agent_cancel",
        "parameters": [
          {
            "name": "showing_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Response"
                },
                "example": {
                  "message": "Showing successfully canceled."
                }
              }
            }
          },
          "404": {
            "description": "No showing initiated by the authenticated user exists with the given id. `message` is an array.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": [
                    "No showing found with the given id."
                  ]
                }
              }
            }
          },
          "422": {
            "description": "The showing could not be canceled, e.g. it was already canceled. `message` is an array.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": [
                    "This showing was already canceled. Canceling user: Jane Agent"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/showings/{showing_id}/initiating_agent_cancel": {
      "post": {
        "summary": "Initiating Agent Cancel",
        "description": "Cancel a showing as the initiating agent (buyer's agent). The authenticated user must be the initiating agent on the showing.",
        "tags": [
          "Showings"
        ],
        "operationId": "showing_initiating_agent_cancel",
        "parameters": [
          {
            "name": "showing_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InitiatingAgentCancellationRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Response"
                },
                "example": {
                  "message": "Showing successfully canceled."
                }
              }
            }
          },
          "403": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "You are not authorized to perform this action."
                }
              }
            }
          },
          "422": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "Unable to cancel showing, please try again later."
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/showings/{showing_id}/counter_proposal": {
      "get": {
        "summary": "Counter Proposals",
        "description": "Get all counter proposals for a specific showing.",
        "tags": [
          "Showings"
        ],
        "parameters": [
          {
            "name": "showing_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "include_rejected",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Whether to include rejected counter proposals in the response. Default is false."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/CounterProposalResponse"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/showing_requests/{showing_request_id}/feedbacks": {
      "get": {
        "summary": "Showing Feedback",
        "description": "Get a list of all Showing feedbacks for this request",
        "tags": [
          "Showings"
        ],
        "parameters": [
          {
            "name": "showing_request_id",
            "in": "path",
            "description": "The id of the showing request.",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShowingFeedbackResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/showings/{showing_id}/messages": {
      "get": {
        "summary": "List Messages",
        "description": "Get all messages on a Showing. The authenticated user must be either the requesting user or the showing agent on the Showing.",
        "tags": [
          "Messages"
        ],
        "operationId": "list_showing_messages",
        "parameters": [
          {
            "name": "showing_id",
            "in": "path",
            "description": "The id of the showing.",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/MessageResponse"
                  }
                }
              }
            }
          },
          "404": {
            "description": "The showing was not found, or the authenticated user is not the requesting user or the showing agent on the showing. This body comes from the framework, not `ErrorResponse`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FrameworkErrorResponse"
                },
                "example": {
                  "status": 404,
                  "error": "Not Found"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create Message",
        "description": "Send a message to the other user on a Showing. The authenticated user must be either the requesting user or the showing agent. Sending a message triggers an SMS notification to the other user and may trigger an organization auto-responder reply.",
        "tags": [
          "Messages"
        ],
        "operationId": "create_showing_message",
        "parameters": [
          {
            "name": "showing_id",
            "in": "path",
            "description": "The id of the showing.",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "message"
                ],
                "properties": {
                  "message": {
                    "type": "object",
                    "required": [
                      "body"
                    ],
                    "properties": {
                      "body": {
                        "type": "string",
                        "description": "The message text. Must be present and 1200 characters or fewer.",
                        "maxLength": 1200,
                        "example": "On my way to the showing now."
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Message was created successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Response"
                },
                "example": {
                  "message": "Successfully added message to showing."
                }
              }
            }
          },
          "404": {
            "description": "The showing was not found, or the authenticated user is not the requesting user or the showing agent on the showing. This body comes from the framework, not `ErrorResponse`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FrameworkErrorResponse"
                },
                "example": {
                  "status": 404,
                  "error": "Not Found"
                }
              }
            }
          },
          "422": {
            "description": "Message could not be created. Returned when the body is blank or too long, when the other agent is no longer available to message, or when the user is not authorized to message on this showing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": [
                    "Body can't be blank"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/showings/{showing_id}/counter_proposal_acceptance": {
      "post": {
        "summary": "Accept Counter-Proposal",
        "description": "Accept a counter-proposal for a showing. The authenticated user must be authorized to accept the counter-proposal.",
        "tags": [
          "Showings"
        ],
        "operationId": "create_counter_proposal_acceptance",
        "parameters": [
          {
            "name": "showing_id",
            "in": "path",
            "description": "The id of the showing.",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "counter_proposal_id": {
                    "type": "integer",
                    "description": "The id of the counter-proposal to accept.",
                    "example": 456
                  }
                },
                "required": [
                  "counter_proposal_id"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Response"
                },
                "example": {
                  "message": "Counter-proposal accepted!"
                }
              }
            }
          },
          "422": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "Unable to continue with this counter-proposal as it's no longer valid. The showing may have been accepted by another agent or the showing was canceled by the initiating agent."
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/showings/{showing_id}/counter_proposal_rejection": {
      "post": {
        "summary": "Reject Counter-Proposal",
        "description": "Reject a counter-proposal for a showing. The authenticated user must be authorized to reject the counter-proposal.",
        "tags": [
          "Showings"
        ],
        "operationId": "create_counter_proposal_rejection",
        "parameters": [
          {
            "name": "showing_id",
            "in": "path",
            "description": "The id of the showing.",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "counter_proposal_id": {
                    "type": "integer",
                    "description": "The id of the counter-proposal to reject.",
                    "example": 456
                  },
                  "rejection_reason": {
                    "type": "string",
                    "description": "Optional reason for rejecting the counter-proposal.",
                    "example": "The proposed time does not work for my client."
                  }
                },
                "required": [
                  "counter_proposal_id"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Response"
                },
                "example": {
                  "message": "Counter-proposal rejected"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/showings/{showing_id}/showing_issue": {
      "get": {
        "summary": "List Showing Issues",
        "description": "List all issues reported against a showing. The authenticated user must\nbe the requesting user on the showing, or an organization admin in that\nuser's organization.\n",
        "tags": [
          "Showings"
        ],
        "operationId": "list_showing_issues",
        "parameters": [
          {
            "name": "showing_id",
            "in": "path",
            "description": "The id of the showing.",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ShowingIssueResponse"
                  }
                }
              }
            }
          },
          "403": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "You are not authorized to perform this action."
                }
              }
            }
          },
          "404": {
            "description": "The showing or issue was not found, or the showing does not belong to the authenticated user. This body comes from the framework, not `ErrorResponse`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FrameworkErrorResponse"
                },
                "example": {
                  "status": 404,
                  "error": "Not Found"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Report Showing Issue",
        "description": "Report an issue with a showing as the initiating agent (buyer's agent).\nThe authenticated user must be the buyer's agent on the showing, the\nshowing must be in `completed` status, and the report must be submitted\nwithin 24 hours of the showing time.\n\nTask lists are reported here too. A task list takes\nreports in any status until it is\npicked up for payout: 24 hours after the later of the scheduled end of\nthe window and the time it was completed. Task lists accept only\n`sa_no_show` (requires an assigned showing agent),\n`unsatisfactory_showing`, `incomplete`, and `other`. Your\norganization's payment-hold rules apply to task lists exactly as they\ndo to showings.\n",
        "tags": [
          "Showings"
        ],
        "operationId": "create_showing_issue",
        "parameters": [
          {
            "name": "showing_id",
            "in": "path",
            "description": "The id of the showing.",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "showing_issue": {
                    "type": "object",
                    "properties": {
                      "issue_type": {
                        "type": "string",
                        "description": "The type of issue being reported.\n",
                        "enum": [
                          "sa_no_show",
                          "buyer_no_show",
                          "unsatisfactory_showing",
                          "showing_canceled",
                          "incomplete",
                          "other"
                        ],
                        "example": "sa_no_show"
                      },
                      "notes": {
                        "type": "string",
                        "description": "Description of the issue. Maximum 400 characters.",
                        "maxLength": 400,
                        "example": "The showing agent did not arrive at the property."
                      }
                    },
                    "required": [
                      "issue_type",
                      "notes"
                    ]
                  }
                },
                "required": [
                  "showing_issue"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "showing_issue_id": {
                      "type": "integer",
                      "description": "The id of the newly created showing issue. Use this id to\nresolve the issue later via the Resolve Showing Issue endpoint.\n"
                    }
                  }
                },
                "example": {
                  "message": "Showing marked as a no-show",
                  "showing_issue_id": 123
                }
              }
            }
          },
          "403": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "Showing is not eligible for an issue report."
                }
              }
            }
          },
          "404": {
            "description": "No showing with the given id was initiated by the authenticated user. This body comes from the framework, not `ErrorResponse`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FrameworkErrorResponse"
                },
                "example": {
                  "status": 404,
                  "error": "Not Found"
                }
              }
            }
          },
          "422": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "Showing is no longer eligible to report an issue"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/showings/{showing_id}/showing_issue/{id}": {
      "get": {
        "summary": "Get Showing Issue",
        "description": "Retrieve a single issue reported against a showing. The authenticated\nuser must be the requesting user on the showing, or an\norganization admin in that user's organization.\n",
        "tags": [
          "Showings"
        ],
        "operationId": "get_showing_issue",
        "parameters": [
          {
            "name": "showing_id",
            "in": "path",
            "description": "The id of the showing.",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "id",
            "in": "path",
            "description": "The id of the showing issue.",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShowingIssueResponse"
                }
              }
            }
          },
          "403": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "You are not authorized to perform this action."
                }
              }
            }
          },
          "404": {
            "description": "The showing or issue was not found, or the showing does not belong to the authenticated user. This body comes from the framework, not `ErrorResponse`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FrameworkErrorResponse"
                },
                "example": {
                  "status": 404,
                  "error": "Not Found"
                }
              }
            }
          }
        }
      },
      "put": {
        "summary": "Resolve Showing Issue",
        "description": "Update a showing issue's resolution state. The default action (`type=resolved`,\nor `type` omitted) marks the issue resolved, which on `incomplete` issues\nreleases the related payment hold so the initiating agent transfer can\nproceed on the next payout cycle.\n\nPassing `type=showing_agent_issue` marks the issue as a showing agent\nissue instead, which removes it from the unresolved queue but blocks\nthe related payment permanently. The authenticated user must be the\ninitiating agent on the showing.\n",
        "tags": [
          "Showings"
        ],
        "operationId": "resolve_showing_issue",
        "parameters": [
          {
            "name": "showing_id",
            "in": "path",
            "description": "The id of the showing.",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "id",
            "in": "path",
            "description": "The id of the showing issue to update.",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "type",
            "in": "query",
            "description": "The resolution type. Defaults to `resolved` when omitted.\n",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "resolved",
                "showing_agent_issue"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Response"
                },
                "example": {
                  "message": "Showing issue marked as resolved."
                }
              }
            }
          },
          "403": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "You are not authorized to perform this action."
                }
              }
            }
          },
          "404": {
            "description": "The showing or issue was not found, or the showing does not belong to the authenticated user. This body comes from the framework, not `ErrorResponse`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FrameworkErrorResponse"
                },
                "example": {
                  "status": 404,
                  "error": "Not Found"
                }
              }
            }
          },
          "422": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "Showing issue is already resolved."
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/showings/{showing_id}/visitors": {
      "post": {
        "summary": "Add Visitor to Showing",
        "description": "Add a visitor to an existing showing, of any showing type - not just\nrentals. The showing's type still caps how many total visitors it can\nhave (1 for most types, 2 for rentals, up to 25 for open houses and\nrental open houses), and visitors may only be added any time up to\nthe showing_at time, while the showing is still active. The\nauthenticated user must be the requesting user on the showing.\n",
        "tags": [
          "Showings"
        ],
        "operationId": "create_showing_visitor",
        "parameters": [
          {
            "name": "showing_id",
            "in": "path",
            "description": "The id of the showing.",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ShowingVisitorWrapper"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Visitor"
                }
              }
            }
          },
          "422": {
            "description": "The visitor could not be added.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "Visitors cannot be added to this showing."
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/showings/{showing_id}/visitors/{id}": {
      "delete": {
        "summary": "Remove Visitor from Showing",
        "description": "Remove a visitor from an existing showing, of any showing type - not\njust rentals. Any visitor may be removed, including the one the\nshowing was originally created with — not just visitors added later\n— but at least one visitor must always remain on the showing. No\nnotification is sent when a visitor is removed.\n",
        "tags": [
          "Showings"
        ],
        "operationId": "delete_showing_visitor",
        "parameters": [
          {
            "name": "showing_id",
            "in": "path",
            "description": "The id of the showing.",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "id",
            "in": "path",
            "description": "The id of the visitor.",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Response"
                },
                "example": {
                  "message": "Visitor removed."
                }
              }
            }
          },
          "422": {
            "description": "The visitor could not be removed. This happens when the\nshowing_at time has passed, or this is the last remaining\nvisitor on the showing (message: \"Cannot remove the last visitor\nfrom this showing.\").\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "Visitors cannot be removed from this showing."
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/showings/rescheduling": {
      "post": {
        "summary": "Reschedule Showing",
        "description": "Create a reschedule request for a showing for which you are either the initiating agent or showing agent.",
        "tags": [
          "Showings"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ShowingRescheduling"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Response"
                },
                "example": {
                  "message": "Requested to reschedule showing"
                }
              }
            }
          },
          "404": {
            "description": "No showing exists with the given id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "Showing not found"
                }
              }
            }
          },
          "422": {
            "description": "The showing could not be rescheduled. When the rescheduling request fails\nvalidation, `message` is an array of validation messages; when the showing\nis not reschedulable, `message` is a string.\n\nThe requested time follows the same rules as a new showing, in the showing's\ntime zone: between 8 am and 8:45 pm, on a 15 minute interval, at least one\nhour from now (or in the future for last-minute showings), and no more than\nseven days from now.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": [
                    "Showing at cannot be before 8 am"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/showings/rescheduling/{showing_rescheduling_id}": {
      "put": {
        "summary": "Reschedule Accept/Decline",
        "description": "Accept or Reject a rescheduling request for a showing.",
        "tags": [
          "Showings"
        ],
        "operationId": "update_showing_rescheduling",
        "parameters": [
          {
            "name": "showing_rescheduling_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "description": "Whether to accept or reject the rescheduling request. Case insensitive.",
                    "enum": [
                      "accept",
                      "reject"
                    ]
                  },
                  "rejection_reason": {
                    "type": "string",
                    "description": "Optional reason shown to the agent who requested the reschedule.\nOnly read when `status` is `reject`. May also be sent nested as\n`showing_rescheduling[rejection_reason]`.\n",
                    "example": "That time no longer works for my client."
                  }
                },
                "required": [
                  "status"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The rescheduling request was accepted or rejected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Response"
                },
                "examples": {
                  "accepted": {
                    "value": {
                      "message": "Accepted rescheduling"
                    }
                  },
                  "rejected": {
                    "value": {
                      "message": "Rejected rescheduling"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "The request body is not valid JSON. This body comes from the framework, not `ErrorResponse`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FrameworkErrorResponse"
                },
                "example": {
                  "status": 400,
                  "error": "Bad Request"
                }
              }
            }
          },
          "404": {
            "description": "No rescheduling request exists with the given id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "Reschedule Request not found"
                }
              }
            }
          },
          "422": {
            "description": "`status` was not `accept` or `reject`, or the rescheduling request could\nno longer be transitioned.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "Invalid status parameter"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/showings/showing_amendment": {
      "post": {
        "summary": "Add Showing to Group",
        "description": "Request to add one or more properties to an existing showing request (showing\ngroup). This is the API behind the \"Add Showing to Group\" action. Your user must\nbe the initiating agent or the showing agent of the showing request.\n\nNothing is added right away. The other agent is notified and must accept the\nrequest (see `PUT /api/v1/showings/showing_amendment/{id}`).\nOnce accepted, a new showing is created in the same group for each property, with\nthe same showing agent, visitors, and notes as the original showing request.\n\nThe showing request must be amendable: check the showing's `amendable?` field\nbefore offering this action. It's `true` only for standard showings whose showings\nare all unconfirmed, confirmed, or completed, and that have no pending request to\nadd showings. Otherwise this returns `422`. Canceled showings don't count, so to\nswap a showing in a group, cancel it (`POST\n/api/v1/showings/{showing_id}/initiating_agent_cancel` with `cancel_type: cancel_one`)\nand then request the new one. Accepted, rejected, and withdrawn requests don't\nblock a new one; only a pending request does, so wait for the response (or send\nseveral properties in one request) before adding more. To clear a pending request\nyou made, withdraw it (`PUT /api/v1/showings/showing_amendment/{id}` with\n`status: withdraw`). A pending request is rejected automatically once any of its\nshowing times passes.\n\nSet `external_id` on a property to have it copied onto the showing that's created\nwhen the request is accepted. The response includes the new request, with the\n`id` and `status` you can track it by. The `showing_amendment` webhook reports\nwhen it's created, accepted, rejected, or withdrawn.\n",
        "tags": [
          "Showings"
        ],
        "operationId": "create_showing_amendment",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ShowingAmendmentRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The request was created and the other agent was notified.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShowingAmendmentCreateResponse"
                }
              }
            }
          },
          "403": {
            "description": "Your user can't make this request, for example because their identity verification isn't complete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "Please complete the identity verification process before continuing."
                }
              }
            }
          },
          "404": {
            "description": "No showing request exists with the given id, or your user is neither its initiating agent nor its showing agent.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "Showing Request not found."
                }
              }
            }
          },
          "422": {
            "description": "The showing request isn't amendable, or the request failed validation.\n`message` is a string holding the first validation error.\n\nEach `showing_at` follows the same rules as a new showing, in the property's\ntime zone: between 8 am and 8:45 pm, on a 15 minute interval, at least one hour\nfrom now, and no more than seven days from now. It also can't match the time of\na showing already in the group, though it can take the time of a canceled one.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "not_amendable": {
                    "value": {
                      "message": "Cannot currently amend this showing request."
                    }
                  },
                  "time_conflict": {
                    "value": {
                      "message": "One of these showing times is in conflict with the original showing request times."
                    }
                  },
                  "invalid_property": {
                    "value": {
                      "message": "Showing amendment properties zip is the wrong length (should be 5 characters)"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/showings/showing_amendment/{id}": {
      "get": {
        "summary": "Get Add Showing to Group Request",
        "description": "Get the most recent \"Add Showing to Group\" request for the showing group that a\nshowing belongs to. Your user must be the initiating agent or the showing agent of\nthe showing. Use the showing's `outstanding_amendment?` field to check whether a\nrequest is waiting on a response before calling this endpoint.\n\nIt returns the most recent request whether it's pending, accepted, rejected, or\nwithdrawn; `status` says which.\n",
        "tags": [
          "Showings"
        ],
        "operationId": "show_showing_amendment",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The id of any showing in the group. For this `GET`, this is a showing id, not a showing amendment id.",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The most recent request for the showing's group.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShowingAmendmentResponse"
                }
              }
            }
          },
          "403": {
            "description": "Your user can't view this request, for example because their identity verification isn't complete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "Please complete the identity verification process before continuing."
                }
              }
            }
          },
          "404": {
            "description": "No showing exists with the given id, your user is neither its initiating agent nor its showing agent, or its group has no request to add showings.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "Showing Amendment not found."
                }
              }
            }
          }
        }
      },
      "put": {
        "summary": "Add Showing to Group Accept/Decline/Withdraw",
        "description": "Accept, reject, or withdraw a pending \"Add Showing to Group\" request. Only the\nagent who didn't make the request can accept or reject it: if the initiating agent\nmade it, the showing agent responds, and the other way around. Only the agent who\nmade the request can withdraw it, which frees the group for a new request.\n\nA request can't be accepted once any of its showing times has passed. Accepting\none then returns `422` and rejects it instead, with `rejection_reason`\n`showing_time_passed`. Pending requests are also checked every few minutes and\nrejected the same way, so a request whose time passes without a response doesn't\nblock the group.\n\nAccepting creates a new showing in the group for each requested property, with the\nproperty's `external_id`. Showings whose `who_schedules` is `buyers_agent` start as\nconfirmed; the rest start as unconfirmed. Each new showing sends a `showing`\nwebhook. When a request is accepted or rejected by an agent, the agent who made\nit is notified. Every change, including a withdrawal or an automatic rejection,\nsends `showing_amendment_updated` through the `showing_amendment` webhook with the\nnew status.\n",
        "tags": [
          "Showings"
        ],
        "operationId": "update_showing_amendment",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The showing amendment id, which is the `id` returned by the `GET` on this path. For this `PUT`, this is not a showing id.",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "description": "Accept or reject the request (the other agent), or withdraw it (the agent who made it). Case insensitive.",
                    "enum": [
                      "accept",
                      "reject",
                      "withdraw"
                    ]
                  }
                },
                "required": [
                  "status"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The request was accepted, rejected, or withdrawn.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Response"
                },
                "examples": {
                  "accepted": {
                    "value": {
                      "message": "Accepted amended showing request"
                    }
                  },
                  "rejected": {
                    "value": {
                      "message": "Rejected amended showing request"
                    }
                  },
                  "withdrawn": {
                    "value": {
                      "message": "Withdrew amended showing request"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Your user can't respond to this request. This happens when they try to accept\nor reject a request they made, withdraw a request they didn't make, aren't an\nagent on the showing group, or the request is no longer pending (accepted,\nrejected, or withdrawn).\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "already_answered": {
                    "value": {
                      "message": "This showing request is no longer amendable."
                    }
                  },
                  "not_allowed": {
                    "value": {
                      "message": "You are not authorized to perform this action."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "No request exists with the given id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "Showing Amendment not found."
                }
              }
            }
          },
          "422": {
            "description": "`status` was missing or not `accept`, `reject`, or `withdraw` (nothing is\nchanged), a requested showing time has passed (the request is rejected), or a\nnew showing could not be created (the request stays pending).\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "invalid_status": {
                    "value": {
                      "message": "Invalid status parameter"
                    }
                  },
                  "showing_time_passed": {
                    "value": {
                      "message": "A requested showing time has passed, so this request was rejected."
                    }
                  },
                  "showing_invalid": {
                    "value": {
                      "message": "Validation failed: Address line1 can't be blank"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/showing_acceptance_prediction": {
      "get": {
        "summary": "Showing Acceptance Prediction",
        "description": "Get a prediction of whether a showing will be claimed using exact ZIP or city history, with a distance-adjusted rate from the nearest observed ZIP for unknown locations. The probability is a conservative reading of that history, so a location with little of it predicts lower than its surrounding area does.",
        "tags": [
          "Showings"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ShowingRequestWrapper"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "If successful, returns a JSON object containing a prediction, the history the prediction was built from, and a list of warning messages.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "prediction": {
                      "type": "number",
                      "description": "The acceptance probability between 0 and 1",
                      "example": 0.85
                    },
                    "confidence": {
                      "type": "object",
                      "description": "Describes the history behind the prediction so a thin prediction can be told from a well-supported one. The probability is a deliberately conservative reading of that history, so a low total_showings means the prediction both leans on the surrounding area and is discounted for the thin sample.",
                      "properties": {
                        "geography_type": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Which history matched: `zip` or `city` for an exact match, `nearest_zip` when the rate was borrowed from the closest ZIP with history, or null when no local history exists and the minimum probability was returned.",
                          "enum": [
                            "zip",
                            "city",
                            "nearest_zip",
                            null
                          ],
                          "example": "zip"
                        },
                        "geography_key": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "The matched ZIP, or `STATE|CITY` for a city match",
                          "example": "80209"
                        },
                        "total_showings": {
                          "type": "integer",
                          "description": "Independent showing opportunities behind the matched rate in the last 12 months. A showing group is one opportunity rather than one per property, and a relisted showing counts with the showing it replaced.",
                          "example": 84
                        },
                        "distance_miles": {
                          "type": [
                            "number",
                            "null"
                          ],
                          "description": "Distance to the borrowed ZIP; null unless geography_type is `nearest_zip`",
                          "example": null
                        }
                      }
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "example": [
                        "Only the first property in the request is being used for prediction."
                      ]
                    }
                  }
                },
                "example": {
                  "prediction": 0.85,
                  "confidence": {
                    "geography_type": "zip",
                    "geography_key": "80209",
                    "total_showings": 84,
                    "distance_miles": null
                  },
                  "warnings": [
                    "Only the first property in the request is being used for prediction."
                  ]
                }
              }
            }
          },
          "403": {
            "description": "The JSON object returned for an unsuccessful request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "403 - Forbidden: Your account does not have access..."
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tasks": {
      "post": {
        "summary": "Create a Task List",
        "description": "Create a new Task List.\n\n**Candidate schedules.** Instead of `showing_at`/`showing_ends_at`, a request with a\nsingle task can send `candidate_schedules`: an ordered list of time windows to try.\nThe task is created on the first one. If no agent claims it within the claim window\n(set by Showami, 30 minutes by default), counted from when the last notification for\nthat window was sent, the task moves to the next window and agents are notified\nagain. The time never changes while notifications are still going out. Windows whose\nstart time has passed are skipped, and if the current window's start time passes the\ntask moves on right away. When the last window is reached the task stays there and\nfollows the usual unassigned flow.\n\nIt is still one task list with one `id`. Moving between windows sends no webhooks.\nYou get the usual `showing_updated` webhook when the task is claimed, with\n`showing_at` set to the window that was used and `claimed_candidate_schedule_position`\ngiving its index.\n",
        "tags": [
          "Tasks"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKeyHeader"
          }
        ],
        "operationId": "api_v1_tasks",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TaskRequestWrapper"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "If successful, returns a JSON object containing a message and the created task list, with the individual tasks nested under `tasks`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskListResponse"
                },
                "example": {
                  "message": "New task successfully created.",
                  "body": [
                    {
                      "id": 1231,
                      "showing_request_id": 1257,
                      "showing_type": "task",
                      "showing_at": "2026-04-16T10:00:00.000-06:00",
                      "time_zone": "Mountain Time (US & Canada)",
                      "duration": 10,
                      "public_notes": "Public notes about the task...",
                      "price": 45,
                      "payout": 28,
                      "status": "unassigned_with_preferred",
                      "external_id": "external_id_123",
                      "address": {
                        "id": 987,
                        "line1": "600 S Broadway",
                        "line2": "Unit 200",
                        "city": "Denver",
                        "state": "CO",
                        "zip": "80209"
                      },
                      "tasks": [
                        {
                          "id": 88,
                          "showing_id": 1231,
                          "task_type": "Property Check",
                          "task_at": "2026-04-16T10:00:00.000-06:00",
                          "task_ends_at": "2026-04-16T20:00:00.000-06:00",
                          "time_zone": "Mountain Time (US & Canada)",
                          "completed": null,
                          "photo_enabled": true,
                          "max_images": 24,
                          "address": {
                            "id": 988,
                            "line1": "600 S Broadway",
                            "line2": "Unit 200",
                            "city": "Denver",
                            "state": "CO",
                            "zip": "80209"
                          },
                          "alt_address": {
                            "id": 989,
                            "line1": "800 S Broadway",
                            "line2": "Unit 300",
                            "city": "Boulder",
                            "state": "CO",
                            "zip": "80301"
                          },
                          "images": []
                        }
                      ]
                    }
                  ],
                  "warnings": []
                }
              }
            }
          },
          "403": {
            "description": "The JSON object returned for an unsuccessful request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "403 - Forbidden: Your account does not have access..."
                }
              }
            }
          },
          "409": {
            "description": "A request with the same `Idempotency-Key` is still being processed. Retry shortly with the same key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "A request with this Idempotency-Key is still being processed. Retry shortly."
                }
              }
            }
          },
          "422": {
            "description": "The task list could not be created. When the task list fails validation,\n`message` is an array of validation messages. Other failures, such as an\nunknown `task_type`, return `message` as a string.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "validation": {
                    "summary": "Validation failure (array)",
                    "value": {
                      "message": [
                        "Price is not valid for the selected showing type"
                      ]
                    }
                  },
                  "unknown_task_type": {
                    "summary": "Unknown task type (string)",
                    "value": {
                      "message": "Invalid task type 'Inspection'. Valid task types are: Drop off/Pick up, Condition Report, Photography/Videography, Property Check, Key Box Installation, Quality Audit, Other"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/task_acceptance/{task_id}": {
      "put": {
        "summary": "Accept a Task List",
        "description": "Mark a Task List as Accepted",
        "tags": [
          "Tasks"
        ],
        "operationId": "api_v1_task_acceptance",
        "parameters": [
          {
            "name": "task_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "commit": {
                    "type": "string",
                    "description": "Whether to approve or reject the task. `acknowledge` behaves the same as `reject`.",
                    "enum": [
                      "approve",
                      "reject",
                      "acknowledge"
                    ]
                  }
                },
                "required": [
                  "commit"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "If successful, returns a JSON object containing a message and the created task list request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Response"
                },
                "example": {
                  "message": "Task Accepted"
                }
              }
            }
          },
          "403": {
            "description": "The JSON object returned for an unsuccessful request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "403 - Forbidden: Your account does not have access..."
                }
              }
            }
          },
          "404": {
            "description": "No task exists with the given id. This body comes from the framework, not `ErrorResponse`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FrameworkErrorResponse"
                },
                "example": {
                  "status": 404,
                  "error": "Not Found"
                }
              }
            }
          },
          "422": {
            "description": "Returned when the task is rejected (commit is `reject` or `acknowledge`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "Task Rejected"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/users/referrals": {
      "post": {
        "summary": "Referral Requests",
        "description": "Create a new referral request",
        "operationId": "api_v1_users_referrals",
        "tags": [
          "Referrals"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReferralRequestWrapper"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "The JSON object returned for a successful request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Response"
                },
                "example": {
                  "message": "Referral successfully created."
                }
              }
            }
          },
          "403": {
            "description": "The JSON object returned for an unsuccessful request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "403 - Forbidden: Your account does not have access..."
                }
              }
            }
          },
          "422": {
            "description": "The referral failed validation. `message` is an array of validation messages.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": [
                    "Email can't be blank"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/rentals": {
      "get": {
        "summary": "Rental Requests",
        "description": "Get a paginated list of all rental showings initiated by the authenticated user.",
        "tags": [
          "Rentals"
        ],
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/RentalResponse"
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create Rental",
        "description": "You may create one or more rental showing(s) using this action. It takes a JSON object containing the parameters of the showing.",
        "tags": [
          "Rentals"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKeyHeader"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RentalShowingRequestWrapper"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShowingResponse"
                }
              }
            }
          },
          "409": {
            "description": "A request with the same `Idempotency-Key` is still being processed. Retry shortly with the same key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "A request with this Idempotency-Key is still being processed. Retry shortly."
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/rentals/{rental_id}/cancel": {
      "put": {
        "summary": "Cancel Rental",
        "description": "You may cancel an existing rental showing.",
        "tags": [
          "Rentals"
        ],
        "parameters": [
          {
            "name": "rental_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Response"
                },
                "example": {
                  "message": "Rental successfully canceled."
                }
              }
            }
          },
          "422": {
            "description": "The rental could not be canceled. When cancellation fails validation, `message`\nis an array of validation messages; when no rental exists with the given id,\n`message` is the string \"No rental showing found with the given id.\"\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "No rental showing found with the given id."
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/rentals/{rental_id}/tenants": {
      "post": {
        "summary": "Add Tenant to Rental",
        "description": "Add a tenant to an existing rental. A rental supports up to two total tenants. Tenants may be added any time after creation, up to the showing_at time.",
        "tags": [
          "Rentals"
        ],
        "parameters": [
          {
            "name": "rental_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RentalTenantWrapper"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Visitor"
                }
              }
            }
          },
          "422": {
            "description": "The tenant could not be added.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "Tenants cannot be added to this showing."
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/rentals/{rental_id}/tenants/{id}": {
      "delete": {
        "summary": "Remove Tenant from Rental",
        "description": "Remove a tenant from an existing rental. Any tenant may be removed, including the one the rental was originally created with — not just tenants added later — but at least one tenant must always remain on the rental. No notification is sent when a tenant is removed.",
        "tags": [
          "Rentals"
        ],
        "parameters": [
          {
            "name": "rental_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Response"
                },
                "example": {
                  "message": "Tenant removed."
                }
              }
            }
          },
          "422": {
            "description": "The tenant could not be removed. This happens when the showing_at\ntime has passed, the showing is not a rental or rental open house,\nor this is the last remaining tenant on the rental (message:\n\"Cannot remove the last visitor from this showing.\").\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "Tenants cannot be removed from this showing."
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/rentals/{rental_id}": {
      "get": {
        "summary": "Rental Request by Id",
        "description": "Get a serialized rental showing object by its id, initiated by the authenticated user.",
        "tags": [
          "Rentals"
        ],
        "parameters": [
          {
            "name": "rental_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RentalResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/consumers": {
      "post": {
        "summary": "Create Consumer",
        "description": "Create a consumer account under the authenticated brokerage.",
        "tags": [
          "Consumers"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Consumer"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Response"
                },
                "example": {
                  "message": "Consumer successfully created."
                }
              }
            }
          },
          "422": {
            "description": "The consumer could not be found or created. When the user fails validation,\n`message` is an array of validation messages; invalid parameters return\n`message` as a string.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": [
                    "Email is invalid"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/consumers/showings": {
      "post": {
        "summary": "Create Consumer Showing",
        "description": "You may create one or more consumer showing(s) using this action. It takes a JSON object containing the parameters of the showing.",
        "tags": [
          "Consumers"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKeyHeader"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConsumerShowingRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShowingCreateResponse"
                }
              }
            }
          },
          "409": {
            "description": "A request with the same `Idempotency-Key` is still being processed. Retry shortly with the same key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "A request with this Idempotency-Key is still being processed. Retry shortly."
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/users/favorite_user/{user_id}": {
      "put": {
        "summary": "Mark a User as a Favorite",
        "description": "Mark a User as a Favorite",
        "tags": [
          "Users"
        ],
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "description": "The id of the user to favorite.",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "description": "If \"add\" is given, the user will be added as a favorite.  If \"remove\" is given, the user will be removed as a favorite.",
                    "enum": [
                      "add",
                      "remove"
                    ]
                  }
                },
                "required": [
                  "type"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserRelationshipResponse"
                },
                "example": {
                  "user_id": 456,
                  "type": "add",
                  "message": "user@example.com added to your favorite agents!"
                }
              }
            }
          },
          "422": {
            "description": "The user could not be found, or the relationship could not be changed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "User not found"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/users": {
      "delete": {
        "summary": "Close Account",
        "description": "Close the authenticated user's Showami account. The account is soft-deleted,\nstored payment information is removed, any active subscription is cancelled,\nand the user is signed out and can no longer log in.\n\nAn account cannot be closed while the user has a pending Showing, either as\nthe requesting agent or as the Showing Agent. Every Showing must first reach\na final status: `paid`, `cancelled`, `expired`, `no_show`, `refunded`, or\n`closed_without_payment`. Showings that are `completed`, `processing_payment`,\nor `cancelled_with_payment` are still awaiting payment and block closure.\n",
        "operationId": "close_user_account",
        "tags": [
          "Users"
        ],
        "responses": {
          "200": {
            "description": "The account was closed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Response"
                },
                "example": {
                  "message": "User account successfully closed."
                }
              }
            }
          },
          "401": {
            "description": "No authenticated user was provided.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "Current user not set."
                }
              }
            }
          },
          "422": {
            "description": "The account has a pending Showing and cannot be closed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "Account cannot be closed while there are pending showings."
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/users/blocked_user/{user_id}": {
      "put": {
        "summary": "Mark a User as Blocked",
        "description": "Mark a User as Blocked",
        "tags": [
          "Users"
        ],
        "parameters": [
          {
            "name": "user_id",
            "in": "path",
            "description": "The id of the user to block.",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "description": "If \"add\" is given, the user will be added as a blocked user for your account.  If \"remove\" is given, the user will be removed as a blocked user.",
                    "enum": [
                      "add",
                      "remove"
                    ]
                  }
                },
                "required": [
                  "type"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserRelationshipResponse"
                },
                "example": {
                  "user_id": 456,
                  "type": "add",
                  "message": "user@example.com successfully blocked."
                }
              }
            }
          },
          "422": {
            "description": "The user could not be found, or the relationship could not be changed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "User not found"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/organizations/users": {
      "post": {
        "summary": "Add a User to an Organization",
        "description": "Add a new user to an organization with the specified user details.",
        "tags": [
          "Users"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrganizationUser"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Response"
                },
                "example": {
                  "message": "Successfully added user to organization."
                }
              }
            }
          },
          "422": {
            "description": "Invalid request parameters. Also returned when the organization does not allow\nShowing Agents and `agent_type` is `showing_agent` or `both`. When the new user\nfails validation, `message` is an array of validation messages.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "This organization does not allow the showing_agent or both agent types."
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Remove a User from an Organization",
        "description": "Remove a user from an organization, by email address.",
        "tags": [
          "Users"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "description": "The email address of the user to remove from the organization."
                  }
                },
                "required": [
                  "email"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Response"
                },
                "example": {
                  "message": "Successfully removed user from organization."
                }
              }
            }
          },
          "422": {
            "description": "Invalid request parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "Unable to remove user from organization."
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/organizations/reports": {
      "get": {
        "summary": "List Available Reports",
        "description": "Return the list of reports the authenticated organization admin can download.\nIncludes all standard reports applicable to the organization (subject to billing\ntype and organization type restrictions) plus any custom reports assigned to the\norganization.\n",
        "tags": [
          "Reports"
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ReportSummary"
                  }
                },
                "example": [
                  {
                    "id": 1,
                    "name": "Showings",
                    "description": "A list of showings that involve one or more of your agents.",
                    "standard": true
                  },
                  {
                    "id": 7,
                    "name": "Agent Performance",
                    "description": "A custom report tailored to your organization.",
                    "standard": false
                  }
                ]
              }
            }
          },
          "401": {
            "description": "The authenticated user is not associated with an Organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "Your account does not have access to the requested feature."
                }
              }
            }
          },
          "403": {
            "description": "The authenticated user is not an Organization Admin.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "You are not authorized to perform this action."
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/organizations/reports/{id}": {
      "get": {
        "summary": "Download a Report",
        "description": "Download a report as a CSV file. The authenticated user must be an Organization\nAdmin and must have access to the requested report (any standard report\napplicable to the organization, or a custom report assigned to the organization).\n",
        "tags": [
          "Reports"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "The ID of the report to download (from `GET /organizations/reports/`)."
          },
          {
            "in": "query",
            "name": "start_date",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Optional start of the report date range (YYYY-MM-DD). Only applied by reports that filter by date."
          },
          {
            "in": "query",
            "name": "end_date",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Optional end of the report date range (YYYY-MM-DD). Only applied by reports that filter by date."
          }
        ],
        "responses": {
          "200": {
            "description": "The CSV report.",
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "403": {
            "description": "The authenticated user does not have access to the report.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "You are not authorized to perform this action."
                }
              }
            }
          },
          "404": {
            "description": "No report with the given id exists.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "Report not found."
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/users/tokens": {
      "post": {
        "summary": "Authenticate with API",
        "description": "Exchange an email and password for an Access Token and Refresh Token.\n\n`POST https://showami.com/users/sign_in` is the same endpoint under its\nDevise route and behaves identically; either may be used.\n\nSend `Content-Type: application/json`. This is one of the two endpoints a\nread-only API key may call with a method other than GET, so the `X-Api-Key`\nheader is still required — only the user headers are not, since obtaining\nthem is the point of the call.\n",
        "operationId": "create_user_token",
        "security": [
          {
            "APIKeyHeader": []
          }
        ],
        "tags": [
          "Authentication"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Login"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignInResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication Failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/refresh_tokens": {
      "post": {
        "summary": "Refresh Access Token",
        "description": "Generate fresh Access Token from valid Refresh Token. This also cycles the Refresh token and returns a new one.",
        "security": [],
        "tags": [
          "Authentication"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RefreshTokensRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RefreshTokensResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid refresh token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/price_suggestions": {
      "get": {
        "summary": "Retrieve Price Suggestions",
        "description": "Get a suggested Showing price based on Showing Type, Zip and Duration",
        "tags": [
          "Price Suggestions"
        ],
        "parameters": [
          {
            "in": "query",
            "name": "showing_type",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The type of showing for which to get price suggestions. Ex/ standard, open_house, etc."
            }
          },
          {
            "in": "query",
            "name": "zip",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The zip code for which to get price suggestions."
            }
          },
          {
            "in": "query",
            "name": "duration",
            "required": true,
            "schema": {
              "type": "number",
              "description": "The duration of the showing in hours."
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A list of price suggestions",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "suggested_price": {
                      "type": "number",
                      "description": "The suggested price in dollars.",
                      "example": 80
                    },
                    "price_suggestion_algorithm": {
                      "type": "string",
                      "description": "The algorithm used to generate the price suggestion.",
                      "example": "zip_average"
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Invalid request parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "message": "Please provide a valid showing type and zip code."
                }
              }
            }
          }
        }
      }
    }
  },
  "webhooks": {
    "showing": {
      "post": {
        "summary": "Showing",
        "description": "A webhook to receive showing data on any change of status for any showing that your user has initiated.",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookSignatureHeader"
          }
        ],
        "requestBody": {
          "description": "A serialized showing object",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ShowingWebhook"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The receiving system should return a 200 status to indicate that the data was received successfully."
          }
        }
      }
    },
    "showing_rescheduling": {
      "post": {
        "summary": "Showing Rescheduling",
        "description": "A webhook to receive create/update of a reschedule showing request for a showing that you are associated with.",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookSignatureHeader"
          }
        ],
        "requestBody": {
          "description": "A serialized showing_rescheduling object",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ShowingReschedulingWebhook"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The receiving system should return a 200 status to indicate that the data was received successfully."
          }
        }
      }
    },
    "message": {
      "post": {
        "summary": "Message",
        "description": "A webhook to receive notification of a new message on any showing that your user has initiated.",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookSignatureHeader"
          }
        ],
        "requestBody": {
          "description": "A serialized message object",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MessageWebhook"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The receiving system should return a 200 status to indicate that the data was received successfully."
          }
        }
      }
    },
    "showing_feedback": {
      "post": {
        "summary": "Showing Feedback",
        "description": "A webhook to receive notification of a new showing feedback on any showing that your user has initiated.",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookSignatureHeader"
          }
        ],
        "requestBody": {
          "description": "A serialized Showing Feedback object",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ShowingFeedbackWebhook"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The receiving system should return a 200 status to indicate that the data was received successfully."
          }
        }
      }
    },
    "counter_proposal": {
      "post": {
        "summary": "Counter Proposal",
        "description": "A webhook to receive notification of a new showing counter-proposal for any showing that your user has initiated.",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookSignatureHeader"
          }
        ],
        "requestBody": {
          "description": "A serialized Counter Proposal object",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CounterProposalWebhook"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The receiving system should return a 200 status to indicate that the data was received successfully."
          }
        }
      }
    },
    "showing_amendment": {
      "post": {
        "summary": "Add Showing to Group",
        "description": "A webhook to receive notification when an \"Add Showing to Group\" request\n(showing amendment) is created on a showing request your user initiated\n(`showing_amendment_created`), and when it's accepted, rejected, or withdrawn\n(`showing_amendment_updated`). It's sent whichever agent made the request.\n\nOn acceptance, the new showings are created right after this webhook, and each\nsends its own `showing` webhook with the property's `external_id`. A rejected\nor withdrawn request creates no showings, so this webhook is the only signal of it.\nA pending request is rejected automatically once any of its showing times passes;\nits `rejection_reason` is then `showing_time_passed`.\n",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookSignatureHeader"
          }
        ],
        "requestBody": {
          "description": "A serialized showing_amendment object",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ShowingAmendmentWebhook"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The receiving system should return a 200 status to indicate that the data was received successfully."
          }
        }
      }
    },
    "agent_checkin": {
      "post": {
        "summary": "Agent Check-In",
        "description": "A webhook to receive notification of a showing agent checking in to or out of any showing that your user has initiated.",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookSignatureHeader"
          }
        ],
        "requestBody": {
          "description": "A serialized agent_checkin object",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentCheckinWebhook"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The receiving system should return a 200 status to indicate that the data was received successfully."
          }
        }
      }
    }
  },
  "components": {
    "parameters": {
      "IdempotencyKeyHeader": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "description": "Optional client-supplied key (up to 255 characters) that makes this request safe\nto retry. A retry with the same key and body returns the showing(s) the original\nrequest created instead of creating new ones; the same key with a different body\nreturns `422`. See \"Idempotent creation\" in the overview.\n",
        "schema": {
          "type": "string",
          "maxLength": 255,
          "example": "3f8e2c1a-9b7d-4e6f-a2c5-1d0b9e8f7a6c"
        }
      },
      "WebhookSignatureHeader": {
        "name": "X-Webhook-Signature",
        "in": "header",
        "required": false,
        "description": "HMAC-SHA256 signature of the raw request body, formatted `sha256=<hex>`,\nwhere the hash is `HMAC-SHA256(signing_secret, raw_request_body)`. Present\nonly when the receiving organization has enabled webhook signing.\n",
        "schema": {
          "type": "string",
          "example": "sha256=4f1c0c3f0e9a2bb5..."
        }
      }
    },
    "schemas": {
      "ShowingResponse": {
        "title": "Showing",
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "The id of the showing",
            "example": 123
          },
          "showing_request_id": {
            "type": "integer",
            "description": "The id of the showing request",
            "example": 456
          },
          "showing_at": {
            "type": "string",
            "description": "The date and time of the showing",
            "example": "2020-10-22T13:00:00.000-06:00"
          },
          "time_zone": {
            "type": "string",
            "description": "The timezone of the showing.",
            "example": "Mountain Time (US & Canada)"
          },
          "duration": {
            "type": "number",
            "description": "The duration of the showing",
            "example": 2.5
          },
          "mls": {
            "type": "string",
            "description": "The MLS number of the showing",
            "example": "12120009"
          },
          "notes": {
            "type": "string",
            "description": "The private notes of the showing (visible to only the initiating agent and showing agent)",
            "example": "Here are the details..."
          },
          "public_notes": {
            "type": "string",
            "description": "The public notes of the showing",
            "example": "We're looking for you to do the following..."
          },
          "access_information": {
            "type": "string",
            "description": "Instructions for accessing the property.",
            "example": "Lockbox code 1234, call (555) 123-4567 on arrival"
          },
          "showing_group": {
            "type": "string",
            "description": "The id of the showing group",
            "example": "40ea31cf-e81b-4c0a-853b-8314b6094aef"
          },
          "buyer_name": {
            "type": "string",
            "deprecated": true,
            "description": "Deprecated: use `visitors` instead — this is the `full_name` of\nthe first entry in `visitors`. The name of the buyer (or, for\nrental/rental open house showings, the primary tenant).\n",
            "example": "Sally Ride"
          },
          "buyer_phone": {
            "type": "string",
            "deprecated": true,
            "description": "Deprecated: use `visitors` instead — this is the `phone` of the\nfirst entry in `visitors`. The buyer's phone number (exactly 10\ndigits, no spaces or special characters).\n",
            "example": 7205551234
          },
          "buyer_type": {
            "type": "string",
            "deprecated": true,
            "description": "Deprecated: use `visitors` instead — this is the `visitor_type`\nof the first entry in `visitors`. The type of buyer.\n",
            "example": "individual",
            "enum": [
              "individual",
              "couple",
              "family"
            ]
          },
          "buyer_external_id": {
            "type": "string",
            "description": "An external identifier for the buyer from the calling/external system",
            "example": "buyer-abc-123"
          },
          "met_buyer": {
            "type": "string",
            "description": "Whether the initiating agent has met the buyer.",
            "enum": [
              "unknown",
              "no",
              "yes"
            ],
            "example": "unknown"
          },
          "price": {
            "type": "integer",
            "description": "The price of the showing",
            "example": 100
          },
          "payout": {
            "type": "integer",
            "description": "The payout of the showing",
            "example": 79
          },
          "charge_amount": {
            "type": "number",
            "description": "The total amount (in dollars) charged to the initiating agent.",
            "example": 49
          },
          "charge_details": {
            "type": "array",
            "description": "Line-item breakdown of the charge, with amounts in cents.",
            "items": {
              "type": "object",
              "properties": {
                "description": {
                  "type": "string",
                  "example": "Showing cost"
                },
                "amount": {
                  "type": "integer",
                  "example": 5000
                }
              }
            }
          },
          "transfer_amount": {
            "type": "number",
            "description": "The total amount (in dollars) transferred to the showing agent.",
            "example": 32
          },
          "transfer_details": {
            "type": "array",
            "description": "Line-item breakdown of the transfer, with amounts in cents.",
            "items": {
              "type": "object",
              "properties": {
                "description": {
                  "type": "string",
                  "example": "Showing payout"
                },
                "amount": {
                  "type": "integer",
                  "example": 3200
                }
              }
            }
          },
          "paid_group_amount": {
            "type": "integer",
            "description": "The total payout amount of all showings in the group",
            "example": 158
          },
          "tip": {
            "type": "integer",
            "description": "The tip of the showing",
            "example": 10
          },
          "tip_allowed?": {
            "type": "boolean",
            "description": "Whether a tip can still be added or changed. True only while the showing is completed and payment has not started.",
            "example": true
          },
          "tip_window_ends_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the tip option closes and payment begins. For a Task list this is 24 hours after the later of the scheduled end of the task window and the approval that completed it, so approving early or late still leaves a full window to tip in. For every other type it is 24 hours after the showing time.",
            "example": "2026-09-10T17:00:00.000Z"
          },
          "status": {
            "type": "string",
            "description": "The status of the showing",
            "example": "unassigned",
            "enum": [
              "unassigned",
              "unconfirmed",
              "confirmed",
              "completed",
              "cancelled",
              "expired",
              "no_show",
              "processing_payment",
              "paid",
              "cancelled_with_payment",
              "unassigned_with_preferred",
              "refunded",
              "in_progress",
              "closed_without_payment"
            ]
          },
          "who_cancelled": {
            "type": "string",
            "description": "Which user cancelled the showing",
            "example": "SA",
            "enum": [
              "SA",
              "BA"
            ]
          },
          "cancellation_notes": {
            "type": "string",
            "description": "The notes of the cancellation",
            "example": "The showing was cancelled because..."
          },
          "reposted": {
            "type": "boolean",
            "description": "The reposted status of the showing"
          },
          "message_count": {
            "type": "integer",
            "description": "The message count of the showing"
          },
          "counter_proposal_count": {
            "type": "integer",
            "description": "The counter proposal count of the showing"
          },
          "cancelable": {
            "type": "boolean",
            "description": "If the requesting agent/client can currently cancel the showing. Tasks can't be canceled once the agent has checked in or any task has been completed."
          },
          "reschedulable": {
            "type": "boolean",
            "description": "If the showing is rescheduleable or not"
          },
          "rescheduling_requested": {
            "type": "boolean",
            "description": "If the a showing rescheduling is requested or not"
          },
          "repostable?": {
            "type": "boolean",
            "description": "If the showing is repostable or not"
          },
          "counter_proposable?": {
            "type": "boolean",
            "description": "If the showing is counter proposable or not"
          },
          "who_schedules": {
            "type": "string",
            "description": "Which user schedules the showing",
            "example": "showing_agent",
            "enum": [
              "showing_agent",
              "buyers_agent"
            ]
          },
          "schedule_details": {
            "type": "string",
            "description": "The details of the schedule",
            "example": "The showing has already been scheduled, the code is..."
          },
          "amendable?": {
            "type": "boolean",
            "description": "If the showing is amendable or not"
          },
          "outstanding_amendment?": {
            "type": "boolean",
            "description": "If the showing has an outstanding amendment or not"
          },
          "review_allowed?": {
            "type": "boolean",
            "description": "Not included in the List Showings (`GET /api/v1/showings`) response.",
            "example": false
          },
          "no_show_eligible?": {
            "type": "boolean",
            "description": "If the showing is no show eligible or not"
          },
          "showing_type": {
            "type": "string",
            "description": "The type of showing",
            "example": "standard"
          },
          "feedback_available?": {
            "type": "boolean",
            "example": false
          },
          "photos_visible?": {
            "type": "boolean",
            "example": false
          },
          "photos_editable?": {
            "type": "boolean",
            "example": false
          },
          "standard_tz_identifier": {
            "type": "string",
            "description": "IANA timezone identifier for the showing.",
            "example": "America/Denver"
          },
          "counter_proposal_exists?": {
            "type": "boolean",
            "example": false
          },
          "counter_proposal_rejected?": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "cannot_confirm_before": {
            "type": "string",
            "description": "The earliest time the showing agent may confirm the showing.",
            "example": "2026-04-16T12:27:32.412-06:00"
          },
          "calendar_addable?": {
            "type": "boolean",
            "example": false
          },
          "original_showing_id": {
            "type": "integer",
            "description": "The id of the original showing",
            "example": 111
          },
          "external_id": {
            "type": "string",
            "description": "The external id of the showing",
            "example": "abc-123"
          },
          "external_app_url": {
            "type": "string",
            "description": "A link into the calling/external app for this showing. When present, it is surfaced as a button on the showing views and can be rendered by the native app.",
            "example": "https://partner.example.com/showings/abc-123"
          },
          "external_app_icon_path": {
            "type": "string",
            "description": "The path to the partner app icon, derived from the organization's settings. Read-only; provided so the native app can render the partner icon alongside the external app link.",
            "example": "partners/app_icons/partner.png"
          },
          "agent_checked_in?": {
            "type": "boolean",
            "example": false
          },
          "agent_checked_in_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "agent_checked_out?": {
            "type": "boolean",
            "example": false
          },
          "agent_checked_out_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "checkin_enabled?": {
            "type": "boolean",
            "example": true
          },
          "nar_buyer_agreement": {
            "type": "boolean",
            "description": "The nar buyer agreement status of the showing"
          },
          "accepted_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "The time the showing was accepted by a showing agent."
          },
          "confirmed_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "The time the showing was first confirmed."
          },
          "showing_agent_visible": {
            "type": "boolean",
            "example": false
          },
          "requesting_agent_visible": {
            "type": "boolean",
            "description": "Not included in the List Showings (`GET /api/v1/showings`) response.",
            "example": false
          },
          "max_photos": {
            "type": "integer",
            "example": 35
          },
          "duplicatable?": {
            "type": "boolean",
            "example": false
          },
          "should_mask_agent_email?": {
            "type": "boolean",
            "example": false,
            "description": "True when the buyers agent's organization masks agent emails and the viewing user is not the buyers agent."
          },
          "prefers_contact_via_messaging?": {
            "type": "boolean",
            "example": false,
            "description": "True when the buyers agent's organization prefers communication through the message center and the viewing user is not the buyers agent."
          },
          "address": {
            "$ref": "#/components/schemas/AddressResponse"
          },
          "user": {
            "$ref": "#/components/schemas/UserResponse"
          },
          "showing_agent": {
            "allOf": [
              {
                "$ref": "#/components/schemas/ShowingAgentResponse"
              },
              {
                "type": "object",
                "properties": {
                  "favorite_or_blocked_status": {
                    "type": "string",
                    "enum": [
                      "none",
                      "favorited",
                      "blocked",
                      "blocked_on_platform"
                    ],
                    "description": "Whether the user who requested the showing has favorited or blocked\nthis showing agent. `blocked` means a new request naming this agent as\nthe preferred agent will be rejected, so don't offer them as a choice.\n`blocked_on_platform` means the agent has been blocked by Showami, so\nrequests naming them will also be rejected; it takes precedence over the\nother values. `none` means neither favorited nor blocked.\n",
                    "example": "none"
                  }
                }
              }
            ]
          },
          "showing_agent_cancellation": {
            "$ref": "#/components/schemas/ShowingAgentCancellationResponse"
          },
          "initiating_agent_cancellation": {
            "$ref": "#/components/schemas/InitiatingAgentCancellationResponse"
          },
          "showing_photos": {
            "type": "array",
            "description": "Not included in the List Showings (`GET /api/v1/showings`) response.",
            "items": {
              "type": "object"
            }
          },
          "tasks": {
            "type": "array",
            "description": "The individual tasks belonging to the task list. Only populated for `task` showings.",
            "items": {
              "$ref": "#/components/schemas/TaskResponse"
            }
          },
          "current_candidate_schedule_position": {
            "type": "integer",
            "description": "For a task list created with `candidate_schedules`, the index of the window it is on now. Only included for those task lists, and only for the requesting user.",
            "example": 0
          },
          "candidate_schedules": {
            "type": "array",
            "description": "For a task list created with `candidate_schedules`, every window sent and how it went. Only included for those task lists, and only for the requesting user.",
            "items": {
              "$ref": "#/components/schemas/TaskCandidateScheduleResponse"
            }
          },
          "supplemental_documents": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "showing_videos": {
            "type": "array",
            "description": "Videos attached to the showing.",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "integer",
                  "example": 1
                },
                "title": {
                  "type": "string",
                  "example": "Showami Training"
                },
                "url": {
                  "type": "string",
                  "example": "https://youtu.be/cg4CvHA3-jA"
                }
              }
            }
          },
          "showing_issues": {
            "type": "array",
            "description": "Issues reported against the showing, including those reported\nthrough the web UI. Use an issue's `id` to resolve it via the\nResolve Showing Issue endpoint.\n",
            "items": {
              "$ref": "#/components/schemas/ShowingIssueResponse"
            }
          },
          "tenants": {
            "type": "array",
            "deprecated": true,
            "description": "Deprecated: use `visitors` instead, which includes the primary\nbuyer/tenant as well. The additional tenants on a rental or rental\nopen house showing — everyone except the primary tenant the rental\nwas created with (see `buyer_name`/`buyer_phone`/`buyer_type`). Use\na tenant's `id` to remove it via the Remove Tenant from Rental\nendpoint. Empty for showing types that do not support additional\ntenants.\n",
            "items": {
              "$ref": "#/components/schemas/Visitor"
            }
          },
          "visitors": {
            "type": "array",
            "description": "Every visitor on the showing — the buyer(s) on a standard, open\nhouse, or inspection showing, or the tenant(s) on a rental or\nrental open house showing. A superset of\n`buyer_name`/`buyer_phone`/`buyer_type`, which only describe the\nfirst entry in this list, and (for rental/rental open house\nshowings) of `tenants`. Limited to a single entry for every\nshowing type except `open_house` and `rental_open_house` (up to\n25 visitors) and `rental` (up to 2). For rental and rental open\nhouse showings, use a visitor's `id` to add or remove them via\nthe Add/Remove Tenant from Rental endpoints.\n",
            "items": {
              "$ref": "#/components/schemas/Visitor"
            }
          }
        }
      },
      "ShowingAgentCancellationResponse": {
        "title": "Showing Agent Cancellation",
        "type": [
          "object",
          "null"
        ],
        "description": "Details about a cancellation made by the showing agent",
        "properties": {
          "id": {
            "type": "integer",
            "description": "The id of the cancellation",
            "example": 123
          },
          "showing_id": {
            "type": "integer",
            "description": "The id of the showing",
            "example": 456
          },
          "reason": {
            "type": "string",
            "description": "The reason for the cancellation",
            "example": "unavailable",
            "enum": [
              "seller_cancelled",
              "unavailable",
              "other",
              "counter_proposal",
              "initiating_agent_requested"
            ]
          },
          "cancel_type": {
            "type": "string",
            "description": "Whether to cancel one showing or all showings in the group",
            "example": "cancel_one",
            "enum": [
              "cancel_one",
              "cancel_all"
            ]
          },
          "notes": {
            "type": "string",
            "description": "Additional notes about the cancellation",
            "example": "I have a scheduling conflict"
          },
          "created_at": {
            "type": "string",
            "description": "When the cancellation was created",
            "example": "2024-07-30T13:00:00.000-06:00"
          }
        }
      },
      "ShowingIssueResponse": {
        "title": "Showing Issue",
        "type": "object",
        "description": "An issue reported against a showing. Issues can be reported through the\nAPI or the web UI and resolved via the Resolve Showing Issue endpoint\nusing the issue's `id`.\n",
        "properties": {
          "id": {
            "type": "integer",
            "description": "The id of the showing issue. Use this to resolve the issue.",
            "example": 123
          },
          "issue_type": {
            "type": "string",
            "description": "The type of issue reported.",
            "enum": [
              "sa_no_show",
              "buyer_no_show",
              "unsatisfactory_showing",
              "showing_canceled",
              "incomplete",
              "other"
            ],
            "example": "incomplete"
          },
          "notes": {
            "type": "string",
            "description": "Description of the issue.",
            "example": "The showing agent did not arrive at the property."
          },
          "resolved?": {
            "type": "boolean",
            "description": "True when the issue has been resolved.",
            "example": false
          },
          "resolved_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the issue was resolved, or null if unresolved."
          },
          "showing_agent_issue?": {
            "type": "boolean",
            "description": "True when the issue has been deemed a showing agent issue.",
            "example": false
          },
          "created_at": {
            "type": "string",
            "description": "When the issue was reported.",
            "example": "2024-07-30T13:00:00.000-06:00"
          },
          "updated_at": {
            "type": "string",
            "description": "When the issue was last updated.",
            "example": "2024-07-30T13:00:00.000-06:00"
          }
        }
      },
      "InitiatingAgentCancellationResponse": {
        "title": "Initiating Agent Cancellation",
        "type": [
          "object",
          "null"
        ],
        "description": "Details about a cancellation made by the initiating agent",
        "properties": {
          "id": {
            "type": "integer",
            "description": "The id of the cancellation",
            "example": 123
          },
          "showing_id": {
            "type": "integer",
            "description": "The id of the showing",
            "example": 456
          },
          "cancel_type": {
            "type": "string",
            "description": "Whether to cancel one showing or all showings in the group",
            "example": "cancel_one",
            "enum": [
              "cancel_one",
              "cancel_all"
            ]
          },
          "notes": {
            "type": "string",
            "description": "Additional notes about the cancellation",
            "example": "The buyer is no longer interested"
          },
          "created_at": {
            "type": "string",
            "description": "When the cancellation was created",
            "example": "2024-07-30T13:00:00.000-06:00"
          },
          "updated_at": {
            "type": "string",
            "description": "When the cancellation was last updated",
            "example": "2024-07-30T13:00:00.000-06:00"
          }
        }
      },
      "InitiatingAgentCancellationRequest": {
        "title": "Initiating Agent Cancellation Request",
        "type": "object",
        "properties": {
          "initiating_agent_cancellation": {
            "type": "object",
            "required": [
              "cancel_type",
              "notes"
            ],
            "properties": {
              "cancel_type": {
                "type": "string",
                "description": "Whether to cancel one showing or all showings in the group",
                "example": "cancel_one",
                "enum": [
                  "cancel_one",
                  "cancel_all"
                ]
              },
              "notes": {
                "type": "string",
                "description": "Notes about why the showing is being cancelled",
                "example": "The buyer is no longer interested"
              }
            }
          }
        }
      },
      "ShowingAgentResponse": {
        "title": "Showing Agent",
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "The id of the showing agent",
            "example": 123
          },
          "email": {
            "type": "string",
            "description": "The email of the showing agent",
            "example": "me@example.com"
          },
          "profile": {
            "$ref": "#/components/schemas/ProfileResponse"
          }
        }
      },
      "UserResponse": {
        "title": "User",
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "The id of the user",
            "example": 456
          },
          "email": {
            "type": "string",
            "description": "The email of the user",
            "example": "agent@example.com"
          },
          "profile": {
            "$ref": "#/components/schemas/ProfileResponse"
          }
        }
      },
      "Address": {
        "title": "Address",
        "type": "object",
        "properties": {
          "line1": {
            "type": "string",
            "description": "The first line of the address",
            "example": "123 Main St"
          },
          "line2": {
            "type": "string",
            "description": "The second line of the address",
            "example": "Apt 1"
          },
          "city": {
            "type": "string",
            "description": "The city of the address",
            "example": "Denver"
          },
          "state": {
            "type": "string",
            "description": "The state of the address",
            "example": "CO"
          },
          "zip": {
            "type": "string",
            "description": "The zip code of the address",
            "example": "80202"
          }
        }
      },
      "AddressResponse": {
        "title": "Address",
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "The id of the address",
            "example": 123
          },
          "line1": {
            "type": "string",
            "description": "The first line of the address",
            "example": "123 Main St"
          },
          "line2": {
            "type": "string",
            "description": "The second line of the address",
            "example": "Apt 1"
          },
          "city": {
            "type": "string",
            "description": "The city of the address",
            "example": "Denver"
          },
          "state": {
            "type": "string",
            "description": "The state of the address",
            "example": "CO"
          },
          "zip": {
            "type": "string",
            "description": "The zip code of the address",
            "example": "80202"
          },
          "latitude": {
            "type": "number",
            "description": "The latitude of the address",
            "example": 39.7392358
          },
          "longitude": {
            "type": "number",
            "description": "The longitude of the address",
            "example": -104.990251
          }
        }
      },
      "CounterProposalResponse": {
        "title": "Counter Proposal",
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "The id of the counter proposal",
            "example": 123
          },
          "showing_at": {
            "type": "string",
            "description": "The date and time of the proposed showing",
            "example": "2024-07-30T13:00:00.000-06:00"
          },
          "time_zone": {
            "type": "string",
            "description": "The timezone of the new proposed showing time",
            "example": "Eastern Time (US & Canada)"
          },
          "payout": {
            "type": "integer",
            "description": "The proposed payout of the counter proposal",
            "example": 79
          },
          "price": {
            "type": "integer",
            "description": "The corresponding price of the proposed payout of the counter proposal",
            "example": 100
          },
          "notes": {
            "type": "string",
            "description": "The notes of the counter proposal",
            "example": "I could do this showing, but for a higher price."
          },
          "user_name": {
            "type": "string",
            "description": "The first name and last initial of the user who created the counter proposal",
            "example": "Richard F"
          },
          "user_stars": {
            "type": "number",
            "format": "float",
            "description": "The star rating of the user who created the counter proposal",
            "example": 4.5
          },
          "rejected_at": {
            "type": "string",
            "description": "The date and time the counter proposal was rejected",
            "example": "2024-07-29T13:00:00.000-06:00"
          },
          "rejection_reason": {
            "type": "string",
            "description": "The reason the counter proposal was rejected",
            "example": "The price is too high."
          }
        }
      },
      "CounterProposalWebhook": {
        "title": "Counter-Proposal Webhook",
        "type": "object",
        "properties": {
          "counter_proposal": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer",
                "description": "The id of the counter_proposal",
                "example": 123
              },
              "showing_at": {
                "type": "string",
                "description": "The date and time of the proposed showing",
                "example": "2024-07-30T13:00:00.000-06:00"
              },
              "user_name": {
                "type": "string",
                "description": "The first name and last initial of the user who created the counter_proposal",
                "example": "Richard F"
              },
              "user_stars": {
                "type": "number",
                "format": "float",
                "description": "The star rating of the user who created the counter_proposal",
                "example": 4.5
              },
              "time_zone": {
                "type": "string",
                "description": "The timezone of the new proposed showing time",
                "example": "Eastern Time (US & Canada)"
              },
              "payout": {
                "type": "integer",
                "description": "The proposed payout of the counter_proposal",
                "example": 79
              },
              "price": {
                "type": "integer",
                "description": "The corresponding price of the proposed payout of the counter_proposal",
                "example": 100
              },
              "notes": {
                "type": "string",
                "description": "The notes of the counter_proposal",
                "example": "I could do this showing, but for a higher price."
              }
            }
          },
          "event_name": {
            "type": "string",
            "description": "The name of the event",
            "example": "counter_proposal_created",
            "enum": [
              "counter_proposal_created"
            ]
          },
          "occurred_at": {
            "type": "string",
            "format": "date-time",
            "description": "The time the event occurred, in ISO 8601 format. Stable across delivery retries.",
            "example": "2024-07-30T13:00:00.000-06:00"
          }
        }
      },
      "AgentCheckinWebhook": {
        "title": "Agent Check-In Webhook",
        "type": "object",
        "properties": {
          "agent_checkin": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer",
                "description": "The id of the agent check-in",
                "example": 123
              },
              "showing_id": {
                "type": "integer",
                "description": "The id of the showing the check-in belongs to",
                "example": 456
              },
              "user_id": {
                "type": "integer",
                "description": "The id of the user (showing agent) who checked in or out",
                "example": 789
              },
              "event_type": {
                "type": "string",
                "description": "Whether the agent checked in to or out of the showing",
                "example": "showing_checkin",
                "enum": [
                  "showing_checkin",
                  "showing_checkout"
                ]
              },
              "latitude": {
                "type": "number",
                "format": "float",
                "description": "The latitude where the check-in occurred",
                "example": 39.6403
              },
              "longitude": {
                "type": "number",
                "format": "float",
                "description": "The longitude where the check-in occurred",
                "example": -106.3742
              },
              "checkout_notes": {
                "type": "string",
                "description": "Notes left by the agent at checkout",
                "example": "Buyer loved the kitchen."
              },
              "request_completion_status": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Whether the property data collection request was completed. This is null for check-ins, legacy records, and non-property-data-collection checkouts.",
                "enum": [
                  "yes",
                  "no",
                  "partially"
                ],
                "example": "partially"
              },
              "created_at": {
                "type": "string",
                "format": "date-time",
                "description": "The time the check-in was recorded",
                "example": "2024-07-30T13:00:00.000-06:00"
              },
              "showing_external_id": {
                "type": "string",
                "description": "The external id of the showing the check-in belongs to",
                "example": "asdf-1234"
              },
              "has_photo": {
                "type": "boolean",
                "description": "Whether a check-in photo was attached",
                "example": true
              }
            }
          },
          "event_name": {
            "type": "string",
            "description": "The name of the event",
            "example": "agent_checkin_created",
            "enum": [
              "agent_checkin_created"
            ]
          },
          "occurred_at": {
            "type": "string",
            "format": "date-time",
            "description": "The time the event occurred, in ISO 8601 format. Stable across delivery retries.",
            "example": "2024-07-30T13:00:00.000-06:00"
          }
        }
      },
      "ProfileResponse": {
        "title": "Profile",
        "type": "object",
        "properties": {
          "first_name": {
            "type": "string",
            "description": "The first name of the user",
            "example": "Richard"
          },
          "last_name": {
            "type": "string",
            "description": "The last name of the user",
            "example": "Feynman"
          },
          "phone1": {
            "type": "string",
            "description": "The user's phone number (exactly 10 digits, no spaces or special characters)",
            "example": 7205551234
          },
          "company": {
            "type": "string",
            "description": "The company of the user",
            "example": "Properties Inc."
          },
          "agent_id": {
            "type": "string",
            "description": "The agent id of the user",
            "example": "AN12345678"
          },
          "license_state": {
            "type": "string",
            "description": "The license state of the user",
            "example": "CO"
          },
          "agent_type": {
            "type": "string",
            "description": "The agent type of the user. Showing Agents are sent as the legacy value\n`sellers_agent`, and `other` users with the showing creator role are sent\nas `showing_creator`.\n",
            "enum": [
              "buyers_agent",
              "sellers_agent",
              "both",
              "client",
              "property_manager",
              "consumer",
              "other",
              "showing_creator"
            ],
            "example": "buyers_agent"
          },
          "avatar": {
            "type": [
              "string",
              "null"
            ],
            "description": "The URL of the user's small avatar image.",
            "example": "https://cdn.showami.com/avatars/123/small.jpg?v=1712345678"
          },
          "avatar_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Same value as `avatar` (the field name the mobile app uses).",
            "example": "https://cdn.showami.com/avatars/123/small.jpg?v=1712345678"
          },
          "avatar_base64": {
            "type": "string",
            "description": "The user's avatar, base64 encoded. Returned by default. Endpoints\nthat support the `exclude_fields` parameter can omit it entirely by\npassing `exclude_fields=avatar_base64`.\n",
            "example": "base64encodedstring"
          },
          "eula": {
            "type": "boolean",
            "description": "Whether the user has accepted the terms of service (legacy name for `accepted_tos`)."
          },
          "accepted_tos": {
            "type": "boolean",
            "description": "Whether the user has accepted the terms of service."
          },
          "geo_box": {
            "type": "string",
            "description": "The map bounding box the user last viewed, as two `(longitude, latitude)`\ncorners. Defaults to the Denver area when not set.\n",
            "example": "(-104.74, 39.97), (-105.23, 39.48)"
          },
          "landlord?": {
            "type": "boolean",
            "description": "Whether the user is a landlord."
          },
          "license_states": {
            "type": "array",
            "description": "The real estate licenses held by the user, one per state.",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "integer",
                  "example": 42
                },
                "state": {
                  "type": "string",
                  "example": "CO"
                },
                "license_number": {
                  "type": "string",
                  "example": "FA100012345"
                },
                "brokerage_name": {
                  "type": "string",
                  "example": "Properties Inc."
                }
              }
            }
          }
        }
      },
      "ShowingRequestWrapper": {
        "title": "Showing Request Wrapper",
        "type": "object",
        "properties": {
          "showing_request": {
            "$ref": "#/components/schemas/ShowingRequest"
          }
        }
      },
      "ShowingRequest": {
        "title": "Showing Request",
        "description": "Provide the buyer/tenant(s) on the showing either via `visitors`, or\nvia the legacy `buyer_name`/`buyer_phone`/`buyer_type` fields — not\nboth. If `visitors` is present (even as an empty array), it is used\nand the legacy fields are ignored; otherwise the legacy fields are\nused to build a single visitor.\n",
        "required": [
          "price",
          "showing_type"
        ],
        "type": "object",
        "properties": {
          "showing_type": {
            "type": "integer",
            "description": "0 - standard, 1 - open_house, 2 - inspection, 4 - rental,\n5 - rental_open_house, 8 - property_data_collection. The exact string value\n(e.g. `property_data_collection`) is also accepted. Which types a user may\nrequest depends on their agent type and Platinum status. Tasks are created\nwith `POST /api/v1/tasks`. Appraisals (3) are no longer accepted; past\nappraisals still appear in responses with `showing_type` `appraisal`.\n",
            "enum": [
              0,
              1,
              2,
              4,
              5,
              8
            ],
            "x-enum-varnames": [
              "standard",
              "open_house",
              "inspection",
              "rental",
              "rental_open_house",
              "property_data_collection"
            ]
          },
          "visitors": {
            "type": "array",
            "description": "The buyer(s) or tenant(s) on the showing. Preferred over the\nlegacy `buyer_name`/`buyer_phone`/`buyer_type` fields, which only\nsupport a single visitor. Limited to a single entry for every\nshowing type except `open_house` and `rental_open_house` (up to\n25 visitors) and `rental` (up to 2).\n",
            "items": {
              "type": "object",
              "required": [
                "full_name",
                "phone",
                "visitor_type"
              ],
              "properties": {
                "full_name": {
                  "type": "string",
                  "example": "Christopher Robbins"
                },
                "phone": {
                  "type": "string",
                  "description": "The visitor's phone number (exactly 10 digits, no spaces or special characters)",
                  "example": 7205551234
                },
                "visitor_type": {
                  "type": "string",
                  "example": "individual",
                  "enum": [
                    "individual",
                    "couple",
                    "family"
                  ]
                }
              }
            }
          },
          "buyer_name": {
            "type": "string",
            "deprecated": true,
            "description": "Deprecated: use `visitors` instead. The buyer's name",
            "example": "Christopher Robbins"
          },
          "buyer_phone": {
            "type": "string",
            "deprecated": true,
            "description": "Deprecated: use `visitors` instead. The buyer's phone number (exactly 10 digits, no spaces or special characters)",
            "example": 7205551234
          },
          "buyer_type": {
            "type": "integer",
            "deprecated": true,
            "description": "Deprecated: use `visitors` instead. Still accepted. 0 - individual, 1 - couple, 2 - family. The exact string value is also accepted.",
            "enum": [
              0,
              1,
              2
            ],
            "x-enum-varnames": [
              "individual",
              "couple",
              "family"
            ]
          },
          "buyer_external_id": {
            "type": "string",
            "description": "An external identifier for the buyer from the calling/external system",
            "example": "buyer-abc-123"
          },
          "met_buyer": {
            "type": "integer",
            "description": "0 - unknown, 1 - no, 2 - yes"
          },
          "price": {
            "type": "integer",
            "description": "The amount willing to pay for each showing in the group"
          },
          "notes": {
            "maxLength": 10000,
            "type": "string",
            "description": "Private Showing notes visible to the accepting Showing Agent. Limited to 2,000 characters by default; Showami can raise your organization's limit up to 10,000.",
            "example": "Private Showing notes visible to the accepting Showing Agent"
          },
          "public_notes": {
            "maxLength": 10000,
            "type": "string",
            "description": "Public Showing notes visible to all users. Limited to 2,000 characters by default; Showami can raise your organization's limit up to 10,000.",
            "example": "Public Showing notes visible to all users"
          },
          "nar_buyer_agreement": {
            "type": "boolean",
            "description": "true - yes, the buyer has a NAR buyer agreement, false - no the buyer does not have a NAR buyer agreement, null - it is unknown or undisclosed if the buyer has a NAR buyer agreement"
          },
          "preferred_agent_1_email": {
            "type": "string"
          },
          "preferred_agent_2_email": {
            "type": "string"
          },
          "preferred_agent_3_email": {
            "type": "string"
          },
          "restricted_user_ids": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Showami user ids of agents who should not be notified about this request,\nfor example an agent who previously canceled on your showing. Restricted\nagents are left out of the new-request notifications. Listing a restricted\nagent as a preferred agent returns a 422.\n",
            "example": [
              1234,
              5678
            ]
          },
          "access_information": {
            "type": "string",
            "maxLength": 400,
            "description": "How to access the property. **Required** for every showing type except\n`standard`, `consumer` and `task` — in practice, required for open house,\ninspection, rental and property data collection requests, and\noptional for a standard showing. Maximum 400 characters.\n\nIn responses, for brokerage-organization users, URLs and North American\nphone numbers are auto-wrapped in `<a>` tags (HTML is sanitized); other\nusers receive raw text.\n",
            "example": "How to access the property (Open House, Inspection, Rental only)"
          },
          "time_zone": {
            "type": "string",
            "description": "The timezone of the showing - 'Alaska', 'Arizona', 'Central Time (US & Canada)', 'Eastern Time (US & Canada)', 'Hawaii', 'Indiana (East)', 'Mountain Time (US & Canada)', 'Pacific Time (US & Canada)'",
            "example": "Mountain Time (US & Canada)"
          },
          "external_app_url": {
            "type": "string",
            "description": "A link into the calling/external app for this showing request. When present, it is surfaced as a button on the showing views and can be rendered by the native app.",
            "example": "https://partner.example.com/showings/abc-123"
          },
          "external_app_icon_path": {
            "type": "string",
            "description": "The path to the partner app icon, derived from the organization's settings. Read-only; provided so the native app can render the partner icon alongside the external app link.",
            "example": "partners/app_icons/partner.png"
          },
          "showing_request_properties_attributes": {
            "$ref": "#/components/schemas/ShowingRequestPropertyWrapper"
          }
        }
      },
      "ShowingRequestPropertyWrapper": {
        "title": "Showing Request Property Wrapper",
        "type": "object",
        "properties": {
          "0": {
            "$ref": "#/components/schemas/ShowingRequestProperty"
          },
          "1": {
            "$ref": "#/components/schemas/ShowingRequestProperty"
          }
        }
      },
      "ShowingRequestProperty": {
        "title": "Showing Request Property",
        "required": [
          "city",
          "line1",
          "showing_at(1i)",
          "showing_at(2i)",
          "showing_at(3i)",
          "showing_at(4i)",
          "showing_at(5i)",
          "state",
          "who_schedules",
          "zip"
        ],
        "type": "object",
        "properties": {
          "showing_at(1i)": {
            "type": "string",
            "description": "The year of the showing",
            "example": "2023"
          },
          "showing_at(2i)": {
            "type": "string",
            "description": "The month of the showing",
            "example": "12"
          },
          "showing_at(3i)": {
            "type": "string",
            "description": "The day of the showing",
            "example": "30"
          },
          "showing_at(4i)": {
            "type": "string",
            "description": "The hour of the showing",
            "example": "16"
          },
          "showing_at(5i)": {
            "type": "string",
            "description": "The minute of the showing",
            "enum": [
              "0",
              "15",
              "30",
              "45"
            ]
          },
          "duration": {
            "type": "number",
            "description": "The length of the appointment in hours (Open House, Inspection, and Property Data Collection showing types only)",
            "example": 1.5
          },
          "mls": {
            "type": "string",
            "description": "The MLS identifier of the property, if available"
          },
          "line1": {
            "type": "string"
          },
          "line2": {
            "type": "string"
          },
          "city": {
            "type": "string"
          },
          "state": {
            "type": "string"
          },
          "zip": {
            "type": "string"
          },
          "who_schedules": {
            "type": "integer",
            "description": "0 - showing_agent, 1 - buyers_agent. The exact string value is also accepted.",
            "enum": [
              0,
              1
            ],
            "x-enum-varnames": [
              "showing_agent",
              "buyers_agent"
            ]
          },
          "schedule_details": {
            "type": "string"
          },
          "external_id": {
            "type": "string",
            "description": "An id to associate with the showing from the calling/external system"
          }
        }
      },
      "ShowingRequestResponse": {
        "title": "Showing Request",
        "type": "object",
        "description": "The serialized showing request, returned by endpoints that return a showing request rather than an individual showing.",
        "properties": {
          "id": {
            "type": "integer",
            "description": "The id of the showing request",
            "example": 456
          },
          "showing_type": {
            "type": "string",
            "description": "The type of showing",
            "example": "standard"
          },
          "buyer_name": {
            "type": "string",
            "deprecated": true,
            "description": "Deprecated: use `visitors` instead — this is the `full_name` of\nthe first entry in `visitors`. The name of the buyer (or, for\nrental/rental open house showings, the primary tenant).\n",
            "example": "Sally Ride"
          },
          "buyer_phone": {
            "type": "string",
            "deprecated": true,
            "description": "Deprecated: use `visitors` instead — this is the `phone` of the\nfirst entry in `visitors`. The buyer's phone number (exactly 10\ndigits, no spaces or special characters).\n",
            "example": 7205551234
          },
          "buyer_type": {
            "type": "string",
            "deprecated": true,
            "description": "Deprecated: use `visitors` instead — this is the `visitor_type`\nof the first entry in `visitors`. The type of buyer.\n",
            "example": "individual",
            "enum": [
              "individual",
              "couple",
              "family"
            ]
          },
          "visitors": {
            "type": "array",
            "description": "Every visitor on the showing request — the buyer(s) on a\nstandard, open house, or inspection showing, or the tenant(s) on\na rental or rental open house showing. A superset of\n`buyer_name`/`buyer_phone`/`buyer_type`, which only describe the\nfirst entry in this list. Limited to a single entry for every\nshowing type except `open_house` and `rental_open_house` (up to\n25 visitors) and `rental` (up to 2). For rental and rental open\nhouse showings, use a visitor's `id` to add or remove them via\nthe Add/Remove Tenant from Rental endpoints.\n",
            "items": {
              "$ref": "#/components/schemas/Visitor"
            }
          },
          "met_buyer": {
            "type": "string",
            "description": "Whether the showing agent has met the buyer",
            "example": "unknown",
            "enum": [
              "unknown",
              "no",
              "yes"
            ]
          },
          "notes": {
            "type": "string",
            "description": "The private notes of the showing request (visible to only the initiating agent and showing agent)",
            "example": "Here are the details..."
          },
          "public_notes": {
            "type": "string",
            "description": "The public notes of the showing request",
            "example": "We're looking for you to do the following..."
          },
          "access_information": {
            "type": "string",
            "description": "Instructions for accessing the property.",
            "example": "Lockbox code 1234, call (555) 123-4567 on arrival"
          },
          "price": {
            "type": "integer",
            "description": "The amount willing to pay for each showing in the group",
            "example": 100
          },
          "preferred_agent_1_email": {
            "type": "string"
          },
          "preferred_agent_2_email": {
            "type": "string"
          },
          "preferred_agent_3_email": {
            "type": "string"
          },
          "repostable?": {
            "type": "boolean",
            "description": "If the showing request is repostable or not"
          },
          "photo_enabled": {
            "type": "boolean",
            "description": "Whether photos may be taken for showings on this showing request"
          },
          "nar_buyer_agreement": {
            "type": "boolean",
            "description": "The nar buyer agreement status of the showing request"
          },
          "external_app_url": {
            "type": "string",
            "description": "A link into the calling/external app for this showing request. When present, it is surfaced as a button on the showing views and can be rendered by the native app.",
            "example": "https://partner.example.com/showings/abc-123"
          },
          "external_app_icon_path": {
            "type": "string",
            "description": "The path to the partner app icon, derived from the organization's settings. Read-only; provided so the native app can render the partner icon alongside the external app link.",
            "example": "partners/app_icons/partner.png"
          },
          "showing_request_properties": {
            "type": "array",
            "description": "The one or two properties associated with the showing request.",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "integer",
                  "example": 789
                },
                "showing_request_id": {
                  "type": "integer",
                  "example": 456
                },
                "mls": {
                  "type": "string",
                  "description": "The MLS identifier of the property, if available"
                },
                "showing_at": {
                  "type": "string",
                  "example": "2020-10-22T13:00:00.000-06:00"
                },
                "showing_ends_at": {
                  "type": "string",
                  "example": "2020-10-22T14:00:00.000-06:00"
                },
                "duration": {
                  "type": "number",
                  "example": 1
                },
                "line1": {
                  "type": "string"
                },
                "line2": {
                  "type": "string"
                },
                "city": {
                  "type": "string"
                },
                "state": {
                  "type": "string"
                },
                "zip": {
                  "type": "string"
                },
                "time_zone": {
                  "type": "string",
                  "example": "Mountain Time (US & Canada)"
                },
                "who_schedules": {
                  "type": "string",
                  "example": "showing_agent",
                  "enum": [
                    "showing_agent",
                    "buyers_agent"
                  ]
                },
                "schedule_details": {
                  "type": "string"
                },
                "photo_enabled": {
                  "type": "boolean"
                },
                "task_type": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            }
          },
          "showings": {
            "type": "array",
            "description": "The showings created from this showing request, included on the Showing Request by Id endpoint.",
            "items": {
              "$ref": "#/components/schemas/ShowingResponse"
            }
          }
        }
      },
      "TaskRequestPropertyWrapper": {
        "title": "Task Request Property Wrapper",
        "type": "object",
        "properties": {
          "0": {
            "$ref": "#/components/schemas/TaskRequestProperty"
          },
          "1": {
            "$ref": "#/components/schemas/TaskRequestProperty"
          }
        }
      },
      "TaskRequestProperty": {
        "title": "Task Request Property",
        "description": "Send either the `showing_at(*)`/`showing_ends_at(*)` fields or `candidate_schedules`,\nnot both.\n",
        "required": [
          "task_type",
          "line1",
          "city",
          "state",
          "zip"
        ],
        "type": "object",
        "properties": {
          "task_type": {
            "type": "string",
            "description": "The type of task",
            "enum": [
              "Drop off/Pick up",
              "Condition Report",
              "Photography/Videography",
              "Property Check",
              "Key Box Installation",
              "Quality Audit",
              "Other"
            ]
          },
          "showing_at(1i)": {
            "type": "string",
            "description": "The year of the showing",
            "example": "2023"
          },
          "showing_at(2i)": {
            "type": "string",
            "description": "The month of the showing",
            "example": "12"
          },
          "showing_at(3i)": {
            "type": "string",
            "description": "The day of the showing",
            "example": "30"
          },
          "showing_at(4i)": {
            "type": "string",
            "description": "The hour of the showing",
            "example": "16"
          },
          "showing_at(5i)": {
            "type": "string",
            "description": "The minute of the showing",
            "enum": [
              "0",
              "15",
              "30",
              "45"
            ]
          },
          "showing_ends_at(1i)": {
            "type": "string",
            "description": "The year of the showing",
            "example": "2023"
          },
          "showing_ends_at(2i)": {
            "type": "string",
            "description": "The month of the showing",
            "example": "12"
          },
          "showing_ends_at(3i)": {
            "type": "string",
            "description": "The day of the showing",
            "example": "30"
          },
          "showing_ends_at(4i)": {
            "type": "string",
            "description": "The hour of the showing",
            "example": "16"
          },
          "showing_ends_at(5i)": {
            "type": "string",
            "description": "The minute of the showing",
            "enum": [
              "0",
              "15",
              "30",
              "45"
            ]
          },
          "line1": {
            "type": "string"
          },
          "line2": {
            "type": "string"
          },
          "city": {
            "type": "string"
          },
          "state": {
            "type": "string"
          },
          "zip": {
            "type": "string"
          },
          "alt_line1": {
            "type": "string"
          },
          "alt_line2": {
            "type": "string"
          },
          "alt_city": {
            "type": "string"
          },
          "alt_state": {
            "type": "string"
          },
          "alt_zip": {
            "type": "string"
          },
          "schedule_details": {
            "type": "string"
          },
          "external_id": {
            "type": "string",
            "description": "An id to associate with the showing from the calling/external system. A task list is a single showing, so only the external_id of its earliest task (by `showing_at`) is kept. If other tasks send a different external_id, it is ignored and the response includes a warning."
          },
          "candidate_schedules": {
            "description": "Time windows to try in order, used instead of `showing_at`/`showing_ends_at`.\nOnly allowed when the request has a single task. Send an object keyed by index\n(`\"0\"`, `\"1\"`, ...), which is ordered by index, or an array. Up to 10 windows.\nEach window follows the same rules as `showing_at` (at least one hour from\nnow, no more than seven days out, between 8am and 8:45pm, on the quarter hour),\nand its end must be after its start. See the endpoint description for how the\ntask moves between windows.\n",
            "oneOf": [
              {
                "type": "object",
                "additionalProperties": {
                  "$ref": "#/components/schemas/TaskCandidateSchedule"
                }
              },
              {
                "type": "array",
                "maxItems": 10,
                "items": {
                  "$ref": "#/components/schemas/TaskCandidateSchedule"
                }
              }
            ],
            "example": {
              "0": {
                "showing_at(1i)": "2026",
                "showing_at(2i)": "11",
                "showing_at(3i)": "9",
                "showing_at(4i)": "9",
                "showing_at(5i)": "00",
                "showing_ends_at(1i)": "2026",
                "showing_ends_at(2i)": "11",
                "showing_ends_at(3i)": "9",
                "showing_ends_at(4i)": "17",
                "showing_ends_at(5i)": "00"
              },
              "1": {
                "showing_at(1i)": "2026",
                "showing_at(2i)": "11",
                "showing_at(3i)": "10",
                "showing_at(4i)": "9",
                "showing_at(5i)": "00",
                "showing_ends_at(1i)": "2026",
                "showing_ends_at(2i)": "11",
                "showing_ends_at(3i)": "10",
                "showing_ends_at(4i)": "17",
                "showing_ends_at(5i)": "00"
              }
            }
          }
        }
      },
      "TaskCandidateSchedule": {
        "title": "Task Candidate Schedule",
        "type": "object",
        "required": [
          "showing_at(1i)",
          "showing_at(2i)",
          "showing_at(3i)",
          "showing_at(4i)",
          "showing_at(5i)",
          "showing_ends_at(1i)",
          "showing_ends_at(2i)",
          "showing_ends_at(3i)",
          "showing_ends_at(4i)",
          "showing_ends_at(5i)"
        ],
        "properties": {
          "showing_at(1i)": {
            "type": "string",
            "description": "The year the window opens",
            "example": "2026"
          },
          "showing_at(2i)": {
            "type": "string",
            "description": "The month the window opens",
            "example": "11"
          },
          "showing_at(3i)": {
            "type": "string",
            "description": "The day the window opens",
            "example": "9"
          },
          "showing_at(4i)": {
            "type": "string",
            "description": "The hour the window opens",
            "example": "9"
          },
          "showing_at(5i)": {
            "type": "string",
            "description": "The minute the window opens",
            "enum": [
              "0",
              "00",
              "15",
              "30",
              "45"
            ]
          },
          "showing_ends_at(1i)": {
            "type": "string",
            "description": "The year the window closes",
            "example": "2026"
          },
          "showing_ends_at(2i)": {
            "type": "string",
            "description": "The month the window closes",
            "example": "11"
          },
          "showing_ends_at(3i)": {
            "type": "string",
            "description": "The day the window closes",
            "example": "9"
          },
          "showing_ends_at(4i)": {
            "type": "string",
            "description": "The hour the window closes",
            "example": "17"
          },
          "showing_ends_at(5i)": {
            "type": "string",
            "description": "The minute the window closes",
            "enum": [
              "0",
              "00",
              "15",
              "30",
              "45"
            ]
          }
        }
      },
      "TaskCandidateScheduleResponse": {
        "title": "Task Candidate Schedule",
        "type": "object",
        "properties": {
          "position": {
            "type": "integer",
            "description": "The window's index in the `candidate_schedules` that were sent, starting at 0.",
            "example": 0
          },
          "showing_at": {
            "type": "string",
            "example": "2026-11-09T09:00:00.000-07:00"
          },
          "showing_ends_at": {
            "type": "string",
            "example": "2026-11-09T17:00:00.000-07:00"
          },
          "status": {
            "type": "string",
            "description": "`current` is the window the task is on now, `claimed` is the window it was\nclaimed on, `unclaimed` was tried without being claimed, `skipped` was passed\nover because its start time had passed, and `pending` hasn't been tried yet.\n",
            "enum": [
              "current",
              "claimed",
              "unclaimed",
              "skipped",
              "pending"
            ],
            "example": "current"
          },
          "attempt_started_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the task moved to this window."
          },
          "attempt_ended_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "When the task moved on from this window because it wasn't claimed."
          }
        }
      },
      "ShowingWebhook": {
        "title": "Showing Webhook",
        "type": "object",
        "properties": {
          "showing": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer",
                "description": "The id of the showing",
                "example": 123
              },
              "showing_at": {
                "type": "string",
                "description": "The date and time of the showing",
                "example": "2024-07-30T13:00:00.000-06:00"
              },
              "mls": {
                "type": "string",
                "description": "The MLS number of the property",
                "example": "1234"
              },
              "notes": {
                "type": "string",
                "description": "Notes about the showing",
                "example": "Some notes..."
              },
              "showing_group": {
                "type": "string",
                "description": "The id of the showing group",
                "example": "6f2ds225-facd-99c5-84d0-cd98f221233"
              },
              "buyer_name": {
                "type": "string",
                "description": "The name of the buyer",
                "example": "Richard Feynman"
              },
              "buyer_phone": {
                "type": "string",
                "description": "The buyer's phone number (exactly 10 digits, no spaces or special characters)",
                "example": 7205551234
              },
              "buyer_type": {
                "type": "string",
                "description": "The type of buyer",
                "example": "individual"
              },
              "buyer_external_id": {
                "type": "string",
                "description": "An external identifier for the buyer from the calling/external system",
                "example": "buyer-abc-123"
              },
              "status": {
                "type": "string",
                "description": "The status of the showing",
                "example": "unassigned",
                "enum": [
                  "unassigned",
                  "unconfirmed",
                  "confirmed",
                  "completed",
                  "cancelled",
                  "expired",
                  "no_show",
                  "processing_payment",
                  "paid",
                  "cancelled_with_payment",
                  "unassigned_with_preferred",
                  "refunded",
                  "in_progress",
                  "closed_without_payment"
                ]
              },
              "external_id": {
                "type": "string",
                "description": "An id to associate with the showing from the calling/external system",
                "example": "asdf-1234"
              },
              "is_repost": {
                "type": "boolean",
                "description": "True when this showing replaces an earlier one, either because the requesting user used \"Edit and Repost\" or because the showing agent canceled and Showami reposted it. The replaced showing is canceled or removed, so a reposted showing arrives as a `showing_created` event with a new `id`; use `original_showing_id` (or your own `external_id`) to tie it back to the original.",
                "example": true
              },
              "original_showing_id": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "The id of the showing this one replaces, or null if it is not a repost. After an \"Edit and Repost\" the original showing is deleted, so this id can no longer be fetched from the API.",
                "example": 122
              },
              "claimed_candidate_schedule_position": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Only included for task lists created with `candidate_schedules`. The index of the window the task list was claimed on, or null until it is claimed. No webhooks are sent while the task list moves between windows.",
                "example": 1
              }
            }
          },
          "event_name": {
            "type": "string",
            "description": "The name of the event",
            "example": "showing_created",
            "enum": [
              "showing_created",
              "showing_updated"
            ]
          },
          "occurred_at": {
            "type": "string",
            "format": "date-time",
            "description": "The time the event occurred, in ISO 8601 format. Stable across delivery retries.",
            "example": "2024-07-30T13:00:00.000-06:00"
          }
        }
      },
      "ShowingRescheduling": {
        "title": "Showing Rescheduling",
        "type": "object",
        "properties": {
          "showing_rescheduling": {
            "type": "object",
            "properties": {
              "showing_id": {
                "type": "integer",
                "description": "The id of the showing to reschedule. Your user can be either the initiating agent or the showing agent.",
                "example": 123
              },
              "showing_at(1i)": {
                "type": "string",
                "description": "The year of the showing",
                "example": "2024"
              },
              "showing_at(2i)": {
                "type": "string",
                "description": "The month of the showing",
                "example": "12"
              },
              "showing_at(3i)": {
                "type": "string",
                "description": "The day of the showing",
                "example": "30"
              },
              "showing_at(4i)": {
                "type": "string",
                "description": "The hour of the showing, from 8 to 20. Times before 8 am or after 8:45 pm are rejected.",
                "example": "16"
              },
              "showing_at(5i)": {
                "type": "string",
                "description": "The minute of the showing. Must be 0, 15, 30, or 45.",
                "example": "0"
              },
              "notes": {
                "type": "string",
                "description": "Notes for the other agent to know why a reschedule request is being made.",
                "example": "I would like to reschedule this showing because..."
              },
              "rejection_reason": {
                "type": "string",
                "description": "Required when rejecting a reschedule request. Explains why the proposed time was declined.",
                "example": "I already have another showing at that time."
              }
            }
          }
        }
      },
      "ShowingAmendmentRequest": {
        "title": "Add Showing to Group Request",
        "type": "object",
        "required": [
          "showing_amendment"
        ],
        "properties": {
          "showing_amendment": {
            "type": "object",
            "required": [
              "showing_request_id",
              "showing_amendment_properties_attributes"
            ],
            "properties": {
              "showing_request_id": {
                "type": "integer",
                "description": "The id of the showing request (group) to add properties to. This is the showing's `showing_request_id`.",
                "example": 123
              },
              "price": {
                "type": "number",
                "description": "The price for each new showing. Defaults to the original showing request's price.",
                "example": 50
              },
              "showing_amendment_properties_attributes": {
                "description": "The properties to add, either as an array or as an object keyed by index\n(\"0\", \"1\", ...).\n",
                "oneOf": [
                  {
                    "type": "array",
                    "minItems": 1,
                    "items": {
                      "$ref": "#/components/schemas/ShowingAmendmentProperty"
                    }
                  },
                  {
                    "type": "object",
                    "additionalProperties": {
                      "$ref": "#/components/schemas/ShowingAmendmentProperty"
                    }
                  }
                ],
                "example": {
                  "0": {
                    "showing_at": "2024-12-30T16:00:00-07:00",
                    "mls": "1234567",
                    "line1": "600 S Broadway",
                    "line2": "Unit 200",
                    "city": "Denver",
                    "state": "CO",
                    "zip": "80209",
                    "who_schedules": "buyers_agent",
                    "schedule_details": "Lockbox code is 1234.",
                    "time_zone": "Mountain Time (US & Canada)"
                  }
                }
              }
            }
          }
        }
      },
      "ShowingAmendmentProperty": {
        "title": "Add Showing to Group Property",
        "type": "object",
        "required": [
          "showing_at",
          "line1",
          "city",
          "state",
          "zip",
          "who_schedules"
        ],
        "properties": {
          "showing_at": {
            "type": "string",
            "format": "date-time",
            "description": "The time of the new showing, in `time_zone`. Instead of `showing_at`, you can\nsend its parts as `showing_at(1i)` (year), `showing_at(2i)` (month),\n`showing_at(3i)` (day), `showing_at(4i)` (hour) and `showing_at(5i)` (minute),\nas on `ShowingRequestProperty`.\n",
            "example": "2024-12-30T16:00:00-07:00"
          },
          "mls": {
            "type": "string",
            "description": "The MLS identifier of the property, if available"
          },
          "line1": {
            "type": "string"
          },
          "line2": {
            "type": "string"
          },
          "city": {
            "type": "string"
          },
          "state": {
            "type": "string",
            "description": "Two-letter state code",
            "example": "CO"
          },
          "zip": {
            "type": "string",
            "description": "Five-digit ZIP code",
            "example": "80209"
          },
          "who_schedules": {
            "type": "string",
            "description": "Who schedules the showing with the listing.",
            "enum": [
              "showing_agent",
              "buyers_agent"
            ]
          },
          "schedule_details": {
            "type": "string",
            "maxLength": 400,
            "description": "Scheduling details for the showing agent"
          },
          "time_zone": {
            "type": "string",
            "description": "The property's time zone, as a Rails time zone name. Defaults to your user's profile time zone.",
            "example": "Mountain Time (US & Canada)"
          },
          "external_id": {
            "type": "string",
            "description": "Your own id for this property, such as a booking id. It's copied onto the showing created when the request is accepted, as that showing's `external_id`.",
            "example": "booking-1234"
          }
        }
      },
      "ShowingAmendmentCreateResponse": {
        "title": "Add Showing to Group Create Response",
        "type": "object",
        "properties": {
          "message": {
            "type": "string",
            "example": "Thank you, we will notify the other agent of your request to add properties to this showing group."
          },
          "showing_amendment": {
            "$ref": "#/components/schemas/ShowingAmendmentResponse"
          }
        }
      },
      "ShowingAmendmentResponse": {
        "title": "Add Showing to Group Response",
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "The showing amendment id. Use it to accept or reject the request.",
            "example": 42
          },
          "requested_by_id": {
            "type": "integer",
            "description": "The id of the agent who made the request"
          },
          "requested_by": {
            "type": "string",
            "description": "The full name of the agent who made the request",
            "example": "Jane Smith"
          },
          "price": {
            "type": [
              "number",
              "null"
            ],
            "description": "The price for each new showing. When null, the original showing request's price is used.",
            "example": 50
          },
          "showing_request_id": {
            "type": "integer"
          },
          "status": {
            "type": "string",
            "description": "Whether the request is waiting on the other agent, was accepted or rejected, or was withdrawn by the agent who made it.",
            "enum": [
              "requested",
              "accepted",
              "rejected",
              "withdrawn"
            ],
            "example": "requested"
          },
          "requested_at": {
            "type": "string",
            "format": "date-time",
            "example": "2024-12-29T09:00:00.000-07:00"
          },
          "accepted_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the request was accepted, or null"
          },
          "rejected_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the request was rejected, or null"
          },
          "rejection_reason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Set when the request was rejected automatically rather than by an agent. `showing_time_passed` means a requested showing time passed while the request was pending. Null otherwise.",
            "enum": [
              "showing_time_passed",
              null
            ]
          },
          "withdrawn_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the agent who made the request withdrew it, or null"
          },
          "showing_amendment_properties": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "integer"
                },
                "showing_amendment_id": {
                  "type": "integer"
                },
                "external_id": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "The `external_id` sent with this property",
                  "example": "booking-1234"
                },
                "mls": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "showing_at": {
                  "type": "string",
                  "format": "date-time",
                  "example": "2024-12-30T16:00:00.000-07:00"
                },
                "line1": {
                  "type": "string"
                },
                "line2": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "city": {
                  "type": "string"
                },
                "state": {
                  "type": "string"
                },
                "zip": {
                  "type": "string"
                },
                "time_zone": {
                  "type": "string",
                  "example": "Mountain Time (US & Canada)"
                },
                "who_schedules": {
                  "type": "string",
                  "enum": [
                    "showing_agent",
                    "buyers_agent"
                  ]
                }
              }
            }
          }
        }
      },
      "ShowingAmendmentWebhook": {
        "title": "Add Showing to Group Webhook",
        "type": "object",
        "properties": {
          "showing_amendment": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer",
                "description": "The showing amendment id",
                "example": 42
              },
              "showing_request_id": {
                "type": "integer",
                "description": "The id of the showing request the showings are added to",
                "example": 123
              },
              "showing_group": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The `showing_group` of the showings in the request. Null when the request has a single showing.",
                "example": "3f1c2e9a-7b1d-4c55-9a7e-0f6d2b8e4a11"
              },
              "status": {
                "type": "string",
                "enum": [
                  "requested",
                  "accepted",
                  "rejected",
                  "withdrawn"
                ],
                "example": "requested"
              },
              "requested_by": {
                "type": "string",
                "description": "The full name of the agent who made the request",
                "example": "Jane Smith"
              },
              "requested_by_id": {
                "type": "integer",
                "description": "The id of the agent who made the request"
              },
              "price": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "The price for each new showing. When null, the original showing request's price is used.",
                "example": 50
              },
              "requested_at": {
                "type": "string",
                "format": "date-time",
                "example": "2024-12-29T09:00:00.000-07:00"
              },
              "accepted_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "rejected_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "rejection_reason": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Set when the request was rejected automatically rather than by an agent. `showing_time_passed` means a requested showing time passed while the request was pending. Null otherwise.",
                "enum": [
                  "showing_time_passed",
                  null
                ]
              },
              "withdrawn_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "When the agent who made the request withdrew it, or null"
              },
              "buyer_external_id": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The buyer external id of the showing request",
                "example": "buyer-1234"
              },
              "showing_amendment_properties": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "integer"
                    },
                    "external_id": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "example": "booking-1234"
                    },
                    "showing_at": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2024-12-30T16:00:00.000-07:00"
                    },
                    "time_zone": {
                      "type": "string",
                      "example": "Mountain Time (US & Canada)"
                    },
                    "mls": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "line1": {
                      "type": "string"
                    },
                    "line2": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "city": {
                      "type": "string"
                    },
                    "state": {
                      "type": "string"
                    },
                    "zip": {
                      "type": "string"
                    },
                    "who_schedules": {
                      "type": "string",
                      "enum": [
                        "showing_agent",
                        "buyers_agent"
                      ]
                    }
                  }
                }
              }
            }
          },
          "event_name": {
            "type": "string",
            "description": "The name of the event",
            "example": "showing_amendment_created",
            "enum": [
              "showing_amendment_created",
              "showing_amendment_updated"
            ]
          },
          "occurred_at": {
            "type": "string",
            "format": "date-time",
            "description": "The time the event occurred, in ISO 8601 format. Stable across delivery retries.",
            "example": "2024-07-30T13:00:00.000-06:00"
          }
        }
      },
      "ShowingReschedulingWebhook": {
        "title": "Showing Rescheduling Webhook",
        "type": "object",
        "properties": {
          "showing_rescheduling": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer",
                "description": "The id of the showing reschedule request",
                "example": 123
              },
              "showing_id": {
                "type": "integer",
                "description": "The id of the showing to reschedule",
                "example": 456
              },
              "showing_at": {
                "type": "string",
                "description": "The date and time of the requested showing time",
                "example": "2024-07-30T13:00:00.000-06:00"
              },
              "requested_by": {
                "type": "string",
                "description": "The name of the user requesting the reschedule",
                "example": "Richard Feynman"
              },
              "notes": {
                "type": "string",
                "description": "Notes about the showing reschedule",
                "example": "Notes explaining why a reschedule is requested"
              },
              "rejection_reason": {
                "type": "string",
                "description": "The reason provided when the reschedule request was declined.",
                "example": "I have another showing at that time."
              },
              "status": {
                "type": "string",
                "description": "The status of the reschedule request",
                "example": "requested",
                "enum": [
                  "requested",
                  "accepted",
                  "rejected"
                ]
              },
              "buyer_external_id": {
                "type": "string",
                "description": "The external ID of the buyer from the associated showing",
                "example": "buyer-1234"
              }
            }
          },
          "event_name": {
            "type": "string",
            "description": "The name of the event",
            "example": "showing_rescheduling_created",
            "enum": [
              "showing_rescheduling_created",
              "showing_rescheduling_updated"
            ]
          },
          "occurred_at": {
            "type": "string",
            "format": "date-time",
            "description": "The time the event occurred, in ISO 8601 format. Stable across delivery retries.",
            "example": "2024-07-30T13:00:00.000-06:00"
          }
        }
      },
      "TaskRequest": {
        "title": "Task Request",
        "required": [
          "price"
        ],
        "type": "object",
        "properties": {
          "price": {
            "type": "integer",
            "description": "The amount willing to pay for each showing in the group"
          },
          "notes": {
            "maxLength": 10000,
            "type": "string",
            "description": "Limited to 2,000 characters by default; Showami can raise your organization's limit up to 10,000.",
            "example": "Private Task notes visible to the accepting Showing Agent"
          },
          "public_notes": {
            "maxLength": 10000,
            "type": "string",
            "description": "Limited to 2,000 characters by default; Showami can raise your organization's limit up to 10,000.",
            "example": "Public Task notes visible to all agents"
          },
          "preferred_agent_1_email": {
            "type": "string"
          },
          "preferred_agent_2_email": {
            "type": "string"
          },
          "preferred_agent_3_email": {
            "type": "string"
          },
          "restricted_user_ids": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Showami user ids of agents who should not be notified about this request,\nfor example an agent who previously canceled on your showing. Restricted\nagents are left out of the new-request notifications. Listing a restricted\nagent as a preferred agent returns a 422.\n",
            "example": [
              1234,
              5678
            ]
          },
          "time_zone": {
            "type": "string",
            "description": "The timezone of the showing - 'Alaska', 'Arizona', 'Central Time (US & Canada)', 'Eastern Time (US & Canada)', 'Hawaii', 'Indiana (East)', 'Mountain Time (US & Canada)', 'Pacific Time (US & Canada)'",
            "example": "Mountain Time (US & Canada)"
          },
          "external_app_url": {
            "type": "string",
            "description": "A link into the calling/external app for this task list. When present, it is surfaced as a button on the task list views and can be rendered by the native app.",
            "example": "https://partner.example.com/tasks/abc-123"
          },
          "buyer_external_id": {
            "type": "string",
            "description": "An external identifier for the buyer from the calling/external system. Kept when the task list is reposted.",
            "example": "buyer-abc-123"
          },
          "showing_request_properties_attributes": {
            "$ref": "#/components/schemas/TaskRequestPropertyWrapper"
          }
        }
      },
      "TaskRequestWrapper": {
        "title": "Task Request Wrapper",
        "type": "object",
        "properties": {
          "showing_request": {
            "$ref": "#/components/schemas/TaskRequest"
          }
        }
      },
      "MessageWebhook": {
        "title": "Message Webhook",
        "type": "object",
        "properties": {
          "message": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer",
                "description": "The id of the message",
                "example": 123
              },
              "showing_id": {
                "type": "integer",
                "description": "The id of the showing this message is associated with",
                "example": 456
              },
              "user_id": {
                "type": "integer",
                "description": "The id of the user who sent the message",
                "example": 789
              },
              "body": {
                "type": "string",
                "description": "The message body",
                "example": "Hi there, thanks for ..."
              }
            }
          },
          "event_name": {
            "type": "string",
            "description": "The name of the event",
            "example": "message_created",
            "enum": [
              "message_created"
            ]
          },
          "occurred_at": {
            "type": "string",
            "format": "date-time",
            "description": "The time the event occurred, in ISO 8601 format. Stable across delivery retries.",
            "example": "2024-07-30T13:00:00.000-06:00"
          }
        }
      },
      "ShowingFeedbackWebhook": {
        "title": "Showing Feedback Webhook",
        "type": "object",
        "properties": {
          "showing_feedback": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer",
                "description": "The id of the showing_feedback",
                "example": 123
              },
              "showing_request_id": {
                "type": "integer",
                "description": "The id of the showing request this feedback is associated with",
                "example": 456
              },
              "responses": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/ShowingFeedbackResponse"
                }
              }
            }
          },
          "event_name": {
            "type": "string",
            "description": "The name of the event",
            "example": "showing_feedback_created",
            "enum": [
              "showing_feedback_created"
            ]
          },
          "occurred_at": {
            "type": "string",
            "format": "date-time",
            "description": "The time the event occurred, in ISO 8601 format. Stable across delivery retries.",
            "example": "2024-07-30T13:00:00.000-06:00"
          }
        }
      },
      "MessageResponse": {
        "title": "Message",
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "The id of the message.",
            "example": 123
          },
          "body": {
            "type": "string",
            "description": "The message text.",
            "example": "On my way to the showing now."
          },
          "user_id": {
            "type": "integer",
            "description": "The id of the user that sent the message.",
            "example": 456
          },
          "created_by": {
            "type": "string",
            "description": "The full name of the user that sent the message.",
            "example": "Jane Agent"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the message was created.",
            "example": "2026-05-06T14:30:00.000Z"
          }
        }
      },
      "ShowingFeedbackResponse": {
        "title": "Showing Feedback",
        "type": "object",
        "properties": {
          "showing_id": {
            "type": "string",
            "description": "ID of the specific showing this feedback is for",
            "example": "123"
          },
          "showing_address": {
            "type": "string",
            "description": "Address of the showing this feedback is for",
            "example": "362 W 12th St. Denver CO, 80123"
          },
          "showing_external_id": {
            "type": "string",
            "description": "An ID to associate the showing with the external system",
            "example": "abc-1234-ext"
          },
          "feedback_responses": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FeedbackDetails"
            }
          }
        }
      },
      "FeedbackDetails": {
        "title": "Showing Feedback Details",
        "type": "object",
        "properties": {
          "question_key": {
            "type": "string",
            "description": "Question key for this feedback question",
            "example": "rental_completed"
          },
          "question": {
            "type": "string",
            "description": "Question text for this feedback question",
            "example": "Was the rental showing completed?"
          },
          "raw_response": {
            "type": "string",
            "description": "Original response value for this feedback question",
            "example": "maybe"
          },
          "human_readable_response": {
            "type": "string",
            "description": "Human readable response for this feedback question",
            "example": "Maybe or N/A"
          }
        }
      },
      "ReferralRequestWrapper": {
        "title": "Referral Request Wrapper",
        "type": "object",
        "required": [
          "referral"
        ],
        "properties": {
          "referral": {
            "$ref": "#/components/schemas/ReferralRequest"
          }
        }
      },
      "ReferralRequest": {
        "title": "Referral Request",
        "type": "object",
        "required": [
          "client_type",
          "first_name",
          "last_name",
          "email",
          "phone",
          "target_price_range",
          "mortgage_status",
          "min_beds",
          "min_baths",
          "address_attributes"
        ],
        "properties": {
          "client_type": {
            "type": "string",
            "description": "The type of client",
            "example": "buyer",
            "enum": [
              "buyer",
              "seller",
              "both"
            ]
          },
          "first_name": {
            "type": "string",
            "description": "The first name of the referral client",
            "example": "Christopher"
          },
          "last_name": {
            "type": "string",
            "description": "The last name of the referral client",
            "example": "Robbins"
          },
          "email": {
            "type": "string",
            "description": "The email of the referral client",
            "example": "client@example.com"
          },
          "phone": {
            "type": "string",
            "description": "The referred person's phone number (exactly 10 digits, no spaces or special characters)",
            "example": 7205551234
          },
          "target_price_range": {
            "type": "string",
            "description": "The price range of the referral property, either buying or selling",
            "example": "$800,001 - $900,000",
            "enum": [
              "$100,000 - $200,000",
              "$200,001 - $300,000",
              "$300,001 - $400,000",
              "$400,001 - $500,000",
              "$500,001 - $600,000",
              "$600,001 - $700,000",
              "$700,001 - $800,000",
              "$800,001 - $900,000",
              "$900,001 - $1,000,000",
              "$1,000,001+"
            ]
          },
          "mortgage_status": {
            "type": "string",
            "description": "The buyer's mortgage status",
            "enum": [
              "Unknown / Has Not Applied",
              "Prequalified",
              "Preapproved",
              "Cash Buyer"
            ]
          },
          "min_beds": {
            "type": "integer",
            "description": "The minimum number of bedrooms in the desired referral property",
            "example": 3,
            "enum": [
              0,
              1,
              2,
              3,
              4,
              5,
              6,
              7
            ]
          },
          "min_baths": {
            "type": "integer",
            "description": "The minimum number of bathrooms in the desired referral property",
            "example": 2,
            "enum": [
              1,
              2,
              3,
              4,
              5,
              6,
              7
            ]
          },
          "details": {
            "type": "string",
            "description": "A detailed explanation of the referral, from one agent to the other.",
            "example": "My client looking for a 3 bedroom, 2 bath home in the Denver area."
          },
          "call_before_contact": {
            "type": "boolean",
            "description": "Whether the receiving agent should call the referring agent before contacting the client.",
            "example": true
          },
          "address_attributes": {
            "description": "The property address. For `client_type: buyer` this is the area the client is\nlooking in and only `city`/`state` are meaningful, so the field is required but\nmay be partially filled; for `seller` and `both` it is the client's property.\n",
            "$ref": "#/components/schemas/Address"
          }
        }
      },
      "RentalResponse": {
        "title": "Rental",
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "The id of the showing",
            "example": 123
          },
          "showing_request_id": {
            "type": "integer",
            "description": "The id of the showing request",
            "example": 456
          },
          "showing_at": {
            "type": "string",
            "description": "The date and time of the showing",
            "example": "2020-10-22T13:00:00.000-06:00"
          },
          "duration": {
            "type": "number",
            "description": "The duration of the showing",
            "example": 2.5
          },
          "notes": {
            "type": "string",
            "description": "The private notes of the showing (visible to only the initiating agent and showing agent)",
            "example": "Here are the details..."
          },
          "public_notes": {
            "type": "string",
            "description": "The public notes of the showing",
            "example": "We're looking for you to do the following..."
          },
          "access_information": {
            "type": "string",
            "description": "Instructions for accessing the property.",
            "example": "Lockbox code 1234, call (555) 123-4567 on arrival"
          },
          "showing_group": {
            "type": "string",
            "description": "The id of the showing group",
            "example": "40ea31cf-e81b-4c0a-853b-8314b6094aef"
          },
          "tenant_name": {
            "type": "string",
            "deprecated": true,
            "description": "Deprecated: use `visitors` instead — this is the `full_name` of\nthe first entry in `visitors`. The name of the primary tenant.\n",
            "example": "Christopher Robbins"
          },
          "tenant_phone": {
            "type": "string",
            "deprecated": true,
            "description": "Deprecated: use `visitors` instead — this is the `phone` of the\nfirst entry in `visitors`. The primary tenant's phone number\n(exactly 10 digits, no spaces or special characters).\n",
            "example": 7205551234
          },
          "tenant_type": {
            "type": "string",
            "deprecated": true,
            "description": "Deprecated: use `visitors` instead — this is the `visitor_type`\nof the first entry in `visitors`. The type of tenant.\n",
            "example": "individual",
            "enum": [
              "individual",
              "couple",
              "family"
            ]
          },
          "tenants": {
            "type": "array",
            "deprecated": true,
            "description": "Deprecated: use `visitors` instead, which includes the primary\ntenant as well. The additional tenants on the rental — everyone\nexcept the primary tenant (see `tenant_name`/`tenant_phone`/\n`tenant_type`). Use a tenant's `id` to remove it via the Remove\nTenant from Rental endpoint.\n",
            "items": {
              "$ref": "#/components/schemas/Visitor"
            }
          },
          "visitors": {
            "type": "array",
            "description": "Every tenant on the rental, including the primary one. A\nsuperset of `tenant_name`/`tenant_phone`/`tenant_type`, which\nonly describe the first entry in this list, and of `tenants`.\nLimited to at most 2 entries. Use a visitor's `id` to add or\nremove them via the Add/Remove Tenant from Rental endpoints.\n",
            "items": {
              "$ref": "#/components/schemas/Visitor"
            }
          },
          "met_buyer": {
            "type": "string",
            "description": "Whether the showing agent has met the tenant",
            "example": "unknown",
            "enum": [
              "unknown",
              "no",
              "yes"
            ]
          },
          "price": {
            "type": "integer",
            "description": "The price of the showing",
            "example": 100
          },
          "payout": {
            "type": "integer",
            "description": "The payout of the showing",
            "example": 79
          },
          "paid_group_amount": {
            "type": "integer",
            "description": "The total payout amount of all showings in the group",
            "example": 158
          },
          "tip": {
            "type": "integer",
            "description": "The tip of the showing",
            "example": 10
          },
          "status": {
            "type": "string",
            "description": "The status of the showing",
            "example": "unassigned",
            "enum": [
              "unassigned",
              "unconfirmed",
              "confirmed",
              "completed",
              "cancelled",
              "expired",
              "no_show",
              "processing_payment",
              "paid",
              "cancelled_with_payment",
              "unassigned_with_preferred",
              "refunded",
              "in_progress",
              "closed_without_payment"
            ]
          },
          "who_cancelled": {
            "type": "string",
            "description": "Which user cancelled the showing",
            "example": "SA",
            "enum": [
              "SA",
              "BA"
            ]
          },
          "reposted": {
            "type": "boolean",
            "description": "The reposted status of the showing"
          },
          "review_allowed?": {
            "type": "boolean",
            "description": "If the showing is reviewable or not"
          },
          "no_show_eligible?": {
            "type": "boolean",
            "description": "If the showing is no show eligible or not"
          },
          "showing_type": {
            "type": "string",
            "description": "The type of showing",
            "example": "rental"
          },
          "feedback_available?": {
            "type": "boolean",
            "description": "If feedback is available for the showing or not"
          },
          "photos_visible?": {
            "type": "boolean",
            "description": "If the showing photos are visible or not"
          },
          "photos_editable?": {
            "type": "boolean",
            "description": "If the showing photos are editable or not"
          },
          "original_showing_id": {
            "type": "integer",
            "description": "The id of the original showing",
            "example": 111
          },
          "external_id": {
            "type": "string",
            "description": "The external id of the showing",
            "example": "abc-123"
          },
          "address": {
            "$ref": "#/components/schemas/AddressResponse"
          },
          "user": {
            "$ref": "#/components/schemas/UserResponse"
          },
          "showing_agent": {
            "$ref": "#/components/schemas/ShowingAgentResponse"
          },
          "showing_photos": {
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        }
      },
      "RentalShowingRequestWrapper": {
        "title": "Rental Showing Request Wrapper",
        "type": "object",
        "properties": {
          "showing_request": {
            "$ref": "#/components/schemas/RentalShowingRequest"
          }
        }
      },
      "RentalTenantWrapper": {
        "title": "Rental Tenant Wrapper",
        "type": "object",
        "properties": {
          "tenant": {
            "$ref": "#/components/schemas/RentalTenant"
          }
        }
      },
      "RentalTenant": {
        "title": "Rental Tenant",
        "required": [
          "tenant_name",
          "tenant_phone",
          "tenant_type"
        ],
        "type": "object",
        "properties": {
          "tenant_name": {
            "type": "string",
            "description": "The tenant's name",
            "example": "Christopher Robbins"
          },
          "tenant_phone": {
            "type": "string",
            "description": "The tenant's phone number (exactly 10 digits, no spaces or special characters)",
            "example": 7205551234
          },
          "tenant_type": {
            "type": "integer",
            "description": "0 - individual, 1 - couple, 2 - family"
          }
        }
      },
      "ShowingVisitorWrapper": {
        "title": "Showing Visitor Wrapper",
        "type": "object",
        "properties": {
          "visitor": {
            "$ref": "#/components/schemas/ShowingVisitor"
          }
        }
      },
      "ShowingVisitor": {
        "title": "Showing Visitor",
        "required": [
          "full_name",
          "phone",
          "visitor_type"
        ],
        "type": "object",
        "properties": {
          "full_name": {
            "type": "string",
            "description": "The visitor's name",
            "example": "Christopher Robbins"
          },
          "phone": {
            "type": "string",
            "description": "The visitor's phone number (exactly 10 digits, no spaces or special characters)",
            "example": 7205551234
          },
          "visitor_type": {
            "type": "string",
            "example": "individual",
            "enum": [
              "individual",
              "couple",
              "family"
            ]
          }
        }
      },
      "Visitor": {
        "title": "Visitor",
        "type": "object",
        "description": "A single visitor on a showing — the buyer on a standard, open house,\nor inspection showing, or a tenant on a rental or rental open house\nshowing.\n",
        "properties": {
          "id": {
            "type": "integer",
            "description": "The id of the visitor. Use this id to add or remove the visitor\nvia the Add/Remove Visitor from Showing endpoints (or, for rental\nand rental open house showings specifically, the Add/Remove\nTenant from Rental endpoints).\n",
            "example": 123
          },
          "full_name": {
            "type": "string",
            "example": "Christopher Robbins"
          },
          "phone": {
            "type": "string",
            "example": 7205551234
          },
          "visitor_type": {
            "type": "string",
            "example": "individual",
            "enum": [
              "individual",
              "couple",
              "family"
            ]
          },
          "tenant_type": {
            "type": "string",
            "deprecated": true,
            "description": "Deprecated: legacy alias for `visitor_type`. Use `visitor_type` instead.",
            "example": "individual"
          }
        }
      },
      "RentalShowingRequest": {
        "title": "Rental Showing Request",
        "required": [
          "access_information",
          "price",
          "tenant_name",
          "tenant_phone",
          "tenant_type"
        ],
        "type": "object",
        "properties": {
          "tenant_name": {
            "type": "string",
            "description": "The tenant's name",
            "example": "Christopher Robbins"
          },
          "tenant_phone": {
            "type": "string",
            "description": "The tenant's phone number (exactly 10 digits, no spaces or special characters)",
            "example": 7205551234
          },
          "tenant_type": {
            "type": "integer",
            "description": "0 - individual, 1 - couple, 2 - family"
          },
          "price": {
            "type": "integer",
            "description": "The amount willing to pay for each showing in the group"
          },
          "public_notes": {
            "maxLength": 10000,
            "type": "string",
            "description": "Public Showing notes visible to all users. Limited to 2,000 characters by default; Showami can raise your organization's limit up to 10,000.",
            "example": "Public Showing notes visible to all users"
          },
          "notes": {
            "maxLength": 10000,
            "type": "string",
            "description": "Private Showing notes visible to the accepting Showing Agent. Limited to 2,000 characters by default; Showami can raise your organization's limit up to 10,000.",
            "example": "Private Showing notes visible to the accepting Showing Agent"
          },
          "access_information": {
            "type": "string",
            "description": "How to access the property.",
            "example": "How to access the property"
          },
          "preferred_agent_1_email": {
            "type": "string",
            "example": "agent@example.com"
          },
          "preferred_agent_2_email": {
            "type": "string",
            "example": "realtor@example.com"
          },
          "preferred_agent_3_email": {
            "type": "string",
            "example": "other@example.com"
          },
          "restricted_user_ids": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Showami user ids of agents who should not be notified about this request,\nfor example an agent who previously canceled on your showing. Restricted\nagents are left out of the new-request notifications. Listing a restricted\nagent as a preferred agent returns a 422.\n",
            "example": [
              1234,
              5678
            ]
          },
          "time_zone": {
            "type": "string",
            "description": "The timezone of the showing - 'Alaska', 'Arizona', 'Central Time (US & Canada)', 'Eastern Time (US & Canada)', 'Hawaii', 'Indiana (East)', 'Mountain Time (US & Canada)', 'Pacific Time (US & Canada)'",
            "example": "Mountain Time (US & Canada)"
          },
          "external_id": {
            "type": "string",
            "description": "An id to associate with the showing from the calling/external system"
          },
          "showing_request_properties_attributes": {
            "$ref": "#/components/schemas/RentalShowingRequestPropertyWrapper"
          }
        }
      },
      "RentalShowingRequestPropertyWrapper": {
        "title": "Rental Showing Request Property Wrapper",
        "type": "object",
        "properties": {
          "0": {
            "$ref": "#/components/schemas/RentalShowingRequestProperty"
          },
          "1": {
            "$ref": "#/components/schemas/RentalShowingRequestProperty"
          }
        }
      },
      "RentalShowingRequestProperty": {
        "title": "Rental Showing Request Property",
        "required": [
          "city",
          "line1",
          "showing_at(1i)",
          "showing_at(2i)",
          "showing_at(3i)",
          "showing_at(4i)",
          "showing_at(5i)",
          "state",
          "zip"
        ],
        "type": "object",
        "properties": {
          "showing_at(1i)": {
            "type": "string",
            "description": "The year of the showing - e.g. \"2023\""
          },
          "showing_at(2i)": {
            "type": "string",
            "description": "The month of the showing - e.g. \"12\""
          },
          "showing_at(3i)": {
            "type": "string",
            "description": "The day of the showing - e.g. \"30\""
          },
          "showing_at(4i)": {
            "type": "string",
            "description": "The hour of the showing - e.g. \"16\""
          },
          "showing_at(5i)": {
            "type": "string",
            "description": "The minute of the showing - e.g. \"15\"",
            "enum": [
              "0",
              "15",
              "30",
              "45"
            ]
          },
          "line1": {
            "type": "string"
          },
          "line2": {
            "type": "string"
          },
          "city": {
            "type": "string"
          },
          "state": {
            "type": "string"
          },
          "zip": {
            "type": "string"
          }
        }
      },
      "OrganizationUser": {
        "title": "Organization User",
        "type": "object",
        "properties": {
          "user": {
            "type": "object",
            "properties": {
              "email": {
                "type": "string",
                "description": "The email address of the user to add to the organization",
                "example": "user@example.com"
              },
              "first_name": {
                "type": "string",
                "description": "The first name of the user",
                "example": "Christopher"
              },
              "last_name": {
                "type": "string",
                "description": "The last name of the user",
                "example": "Robbins"
              },
              "phone1": {
                "type": "string",
                "description": "The user's phone number (exactly 10 digits, no spaces or special characters)",
                "example": 7205551234
              },
              "license_state": {
                "type": "string",
                "description": "The state where the user holds their license",
                "example": "CO"
              },
              "agent_id": {
                "type": "string",
                "description": "The license number of the user",
                "example": "LIC12345678"
              },
              "agent_type": {
                "type": "string",
                "description": "The type of agent. Organizations that do not allow Showing Agents only\naccept `initiating_agent`.\n",
                "enum": [
                  "initiating_agent",
                  "showing_agent",
                  "both"
                ],
                "example": "both"
              },
              "time_zone": {
                "type": "string",
                "description": "The timezone of the user",
                "enum": [
                  "Alaska",
                  "Arizona",
                  "Central Time (US & Canada)",
                  "Eastern Time (US & Canada)",
                  "Hawaii",
                  "Indiana (East)",
                  "Mountain Time (US & Canada)",
                  "Pacific Time (US & Canada)"
                ],
                "example": "Pacific Time (US & Canada)"
              }
            },
            "required": [
              "email",
              "first_name",
              "last_name",
              "phone1",
              "license_state",
              "agent_id",
              "agent_type",
              "time_zone"
            ]
          }
        }
      },
      "ReportSummary": {
        "title": "Report Summary",
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "The unique identifier of the report, used to download it.",
            "example": 1
          },
          "name": {
            "type": "string",
            "description": "The human-readable name of the report.",
            "example": "Showings"
          },
          "description": {
            "type": "string",
            "description": "A short description of what the report contains.",
            "example": "A list of showings that involve one or more of your agents."
          },
          "standard": {
            "type": "boolean",
            "description": "True for reports available to all eligible organizations; false for reports custom-assigned to this organization.",
            "example": true
          }
        }
      },
      "Consumer": {
        "title": "Consumer",
        "type": "object",
        "properties": {
          "user": {
            "type": "object",
            "properties": {
              "email": {
                "type": "string",
                "description": "The consumer's email",
                "example": "consumer@example.com"
              },
              "first_name": {
                "type": "string",
                "description": "The consumer's first name",
                "example": "Person"
              },
              "last_name": {
                "type": "string",
                "description": "The consumer's last name",
                "example": "McPerson"
              },
              "phone1": {
                "type": "string",
                "description": "The consumer's phone",
                "example": "5554441111"
              }
            }
          }
        }
      },
      "ConsumerShowingRequest": {
        "title": "Consumer Showing Request",
        "type": "object",
        "properties": {
          "consumer": {
            "type": "string",
            "description": "The consumer's email",
            "example": "consumer@example.com"
          },
          "showing_request": {
            "type": "object",
            "properties": {
              "buyer_type": {
                "type": "integer",
                "description": "How the consumer will be showing up to the showing: 0 - individual, 1 - couple, 2 - family",
                "enum": [
                  0,
                  1,
                  2
                ],
                "x-enum-varnames": [
                  "individual",
                  "couple",
                  "family"
                ],
                "example": 0
              },
              "price": {
                "type": "integer",
                "description": "Something",
                "example": 99
              },
              "public_notes": {
                "type": "string",
                "description": "Something",
                "example": "Public notes..."
              },
              "time_zone": {
                "type": "string",
                "description": "Something",
                "example": "Eastern Time (US & Canada)"
              },
              "restricted_user_ids": {
                "type": "array",
                "items": {
                  "type": "integer"
                },
                "description": "Showami user ids of agents who should not be notified about this request,\nfor example an agent who previously canceled on your showing. Restricted\nagents are left out of the new-request notifications. Listing a restricted\nagent as a preferred agent returns a 422.\n",
                "example": [
                  1234,
                  5678
                ]
              },
              "showing_request_properties_attributes": {
                "$ref": "#/components/schemas/RentalShowingRequestPropertyWrapper"
              }
            }
          }
        }
      },
      "PropertyDataCollectionRequestWrapper": {
        "title": "Property Data Collection Request Wrapper",
        "type": "object",
        "properties": {
          "showing_request": {
            "$ref": "#/components/schemas/PropertyDataCollectionRequest"
          }
        }
      },
      "PropertyDataCollectionRequest": {
        "title": "Property Data Collection Request",
        "required": [
          "access_information",
          "price",
          "showing_type",
          "showing_request_properties_attributes"
        ],
        "type": "object",
        "properties": {
          "showing_type": {
            "type": "string",
            "description": "Must be `property_data_collection` for this endpoint. The integer equivalent (`8`) is also accepted.",
            "enum": [
              "property_data_collection"
            ],
            "example": "property_data_collection"
          },
          "price": {
            "type": "integer",
            "description": "The amount willing to pay for the property data collection appointment.",
            "example": 50
          },
          "access_information": {
            "type": "string",
            "description": "Instructions the showing agent will need in order to access the property and complete the data collection workflow.",
            "example": "You'll need the following app to do ABC..."
          },
          "notes": {
            "maxLength": 10000,
            "type": "string",
            "description": "Private notes visible to the accepting Showing Agent. Limited to 2,000 characters by default; Showami can raise your organization's limit up to 10,000."
          },
          "public_notes": {
            "maxLength": 10000,
            "type": "string",
            "description": "Public notes visible to all users. Limited to 2,000 characters by default; Showami can raise your organization's limit up to 10,000."
          },
          "time_zone": {
            "type": "string",
            "description": "The timezone of the appointment - 'Alaska', 'Arizona', 'Central Time (US & Canada)', 'Eastern Time (US & Canada)', 'Hawaii', 'Indiana (East)', 'Mountain Time (US & Canada)', 'Pacific Time (US & Canada)'. If omitted, the initiating user's default timezone is used.",
            "example": "Mountain Time (US & Canada)"
          },
          "external_app_url": {
            "type": "string",
            "description": "A link into the calling/external app for this appointment. When present, it is surfaced as a button on the showing views and can be rendered by the native app.",
            "example": "https://partner.example.com/showings/abc-123"
          },
          "restricted_user_ids": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Showami user ids of agents who should not be notified about this request,\nfor example an agent who previously canceled on your showing. Restricted\nagents are left out of the new-request notifications. Listing a restricted\nagent as a preferred agent returns a 422.\n",
            "example": [
              1234,
              5678
            ]
          },
          "showing_request_properties_attributes": {
            "$ref": "#/components/schemas/PropertyDataCollectionRequestPropertyWrapper"
          }
        }
      },
      "PropertyDataCollectionRequestPropertyWrapper": {
        "title": "Property Data Collection Request Property Wrapper",
        "type": "object",
        "properties": {
          "0": {
            "$ref": "#/components/schemas/PropertyDataCollectionRequestProperty"
          }
        }
      },
      "PropertyDataCollectionRequestProperty": {
        "title": "Property Data Collection Request Property",
        "required": [
          "city",
          "duration",
          "line1",
          "showing_at(1i)",
          "showing_at(2i)",
          "showing_at(3i)",
          "showing_at(4i)",
          "showing_at(5i)",
          "state",
          "zip"
        ],
        "type": "object",
        "properties": {
          "showing_at(1i)": {
            "type": "string",
            "description": "The year of the appointment",
            "example": "2026"
          },
          "showing_at(2i)": {
            "type": "string",
            "description": "The month of the appointment",
            "example": "04"
          },
          "showing_at(3i)": {
            "type": "string",
            "description": "The day of the appointment",
            "example": "16"
          },
          "showing_at(4i)": {
            "type": "string",
            "description": "The hour of the appointment",
            "example": "14"
          },
          "showing_at(5i)": {
            "type": "string",
            "description": "The minute of the appointment",
            "enum": [
              "0",
              "15",
              "30",
              "45"
            ],
            "example": "30"
          },
          "duration": {
            "type": "number",
            "description": "The length of the appointment in hours (Open House, Inspection, and Property Data Collection showing types only)",
            "example": 0.5
          },
          "line1": {
            "type": "string",
            "description": "The first line of the property address.",
            "example": "1 Bridge St"
          },
          "line2": {
            "type": "string",
            "description": "The second line of the property address."
          },
          "city": {
            "type": "string",
            "example": "Vail"
          },
          "state": {
            "type": "string",
            "example": "CO"
          },
          "zip": {
            "type": "string",
            "example": "81657"
          },
          "external_id": {
            "type": "string",
            "description": "An id to associate with the appointment from the calling/external system.",
            "example": "ext-id-abc1234"
          }
        }
      },
      "ShowingCreateResponse": {
        "title": "Showing Create Response",
        "type": "object",
        "properties": {
          "message": {
            "type": "string",
            "description": "A human-readable success message.",
            "example": "New showing successfully created."
          },
          "body": {
            "type": "array",
            "description": "The newly created showings, one per showing time requested.",
            "items": {
              "$ref": "#/components/schemas/ShowingResponse"
            }
          }
        }
      },
      "TaskResponse": {
        "title": "Task",
        "type": "object",
        "description": "An individual task belonging to a task list.",
        "properties": {
          "id": {
            "type": "integer",
            "description": "The id of the task. Use this id with the Task Acceptance, Task Completion, and Task Image endpoints.",
            "example": 88
          },
          "showing_id": {
            "type": "integer",
            "description": "The id of the task list showing this task belongs to.",
            "example": 1231
          },
          "task_type": {
            "type": "string",
            "description": "The name of the task type.",
            "example": "Property Check"
          },
          "description": {
            "type": "string",
            "description": "The description of the task.",
            "example": "Check the property for any damage..."
          },
          "task_at": {
            "type": "string",
            "description": "The date and time the task window opens.",
            "example": "2026-04-16T10:00:00.000-06:00"
          },
          "task_ends_at": {
            "type": "string",
            "description": "The date and time the task window closes.",
            "example": "2026-04-16T20:00:00.000-06:00"
          },
          "time_zone": {
            "type": "string",
            "description": "The timezone of the task list showing.",
            "example": "Mountain Time (US & Canada)"
          },
          "completed": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Whether the showing agent has marked the task complete. Null until the task is acted on.",
            "example": null
          },
          "completion_notes": {
            "type": [
              "string",
              "null"
            ],
            "description": "Notes left by the showing agent when completing the task.",
            "example": null
          },
          "completed_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "The date and time the task was marked complete.",
            "example": null
          },
          "approved_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "The date and time the task was approved by the initiating agent.",
            "example": null
          },
          "rejected_at": {
            "type": [
              "string",
              "null"
            ],
            "description": "The date and time the task was rejected by the initiating agent.",
            "example": null
          },
          "photo_enabled": {
            "type": "boolean",
            "description": "Whether photos are required in order to complete the task.",
            "example": true
          },
          "quick_task": {
            "type": "boolean",
            "description": "Whether the task list is priced within the quick task range.",
            "example": false
          },
          "max_images": {
            "type": "integer",
            "description": "The maximum number of images that may be attached to the task.",
            "example": 24
          },
          "address": {
            "$ref": "#/components/schemas/AddressResponse"
          },
          "alt_address": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/AddressResponse"
              },
              {
                "type": "null"
              }
            ],
            "description": "The alternate address for the task, or null if there isn't one."
          },
          "images": {
            "type": "array",
            "description": "Images attached to the task.",
            "items": {
              "type": "object"
            }
          }
        }
      },
      "TaskListResponse": {
        "title": "Task List Response",
        "type": "object",
        "properties": {
          "message": {
            "type": "string",
            "description": "A human-readable success message.",
            "example": "New task successfully created."
          },
          "body": {
            "type": "array",
            "description": "The newly-created task list showing(s), each with their tasks nested under `tasks`.",
            "items": {
              "$ref": "#/components/schemas/ShowingResponse"
            }
          },
          "warnings": {
            "type": "array",
            "description": "Problems with the request that didn't stop the task list from being created. Empty when there are none.",
            "items": {
              "type": "string"
            },
            "example": [
              "A task list is a single showing, so it only keeps the external_id of its earliest task (\"ext-1\"). Ignored external_ids: \"ext-2\"."
            ]
          }
        }
      },
      "UserRelationshipResponse": {
        "title": "User Relationship Response",
        "type": "object",
        "properties": {
          "user_id": {
            "type": "integer",
            "description": "The id of the user the relationship was changed for.",
            "example": 456
          },
          "type": {
            "type": "string",
            "description": "The action that was applied, echoed back from the request.",
            "enum": [
              "add",
              "remove"
            ],
            "example": "add"
          },
          "message": {
            "type": "string",
            "example": "user@example.com added to your favorite agents!"
          }
        }
      },
      "Response": {
        "title": "Response",
        "type": "object",
        "properties": {
          "message": {
            "type": "string"
          }
        }
      },
      "ErrorResponse": {
        "title": "ErrorResponse",
        "type": "object",
        "description": "Every error response is a JSON object with a `message` key. Depending on the endpoint\nand failure, `message` is either a single string or an array of strings. Validation\nfailures usually return an array, with one entry per failed validation. Clients should\nhandle both forms. A few errors raised before the endpoint renders (malformed JSON,\nsome missing records) use `FrameworkErrorResponse` instead, which has no `message` key.\n",
        "properties": {
          "message": {
            "oneOf": [
              {
                "type": "string",
                "example": "Error message"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "example": [
                  "Showing at can't be blank",
                  "Price is not valid for the selected showing type"
                ]
              }
            ],
            "description": "A human-readable error message, or an array of messages.",
            "example": "Error message"
          }
        }
      },
      "FrameworkErrorResponse": {
        "title": "FrameworkErrorResponse",
        "type": "object",
        "description": "The error body Rails sends when a request fails before the endpoint can\nrender its own `ErrorResponse`. This happens on a malformed JSON body (400)\nand on endpoints that look up a record without handling a missing one (404).\nIt has `status` and `error` keys and no `message` key. It is JSON only when\nthe request sends `Accept: application/json`; otherwise the body is an HTML\nerror page.\n",
        "properties": {
          "status": {
            "type": "integer",
            "description": "The HTTP status code.",
            "example": 404
          },
          "error": {
            "type": "string",
            "description": "The HTTP status text.",
            "example": "Not Found"
          }
        }
      },
      "Login": {
        "title": "Login",
        "type": "object",
        "properties": {
          "user": {
            "type": "object",
            "properties": {
              "email": {
                "type": "string",
                "example": "user@example.com"
              },
              "password": {
                "type": "string",
                "example": "some_secure_password"
              }
            }
          }
        }
      },
      "RefreshTokensRequest": {
        "title": "RefreshTokensRequest",
        "type": "object",
        "properties": {
          "refresh_token": {
            "type": "string",
            "example": "abc123"
          }
        }
      },
      "SignInResponse": {
        "title": "SignInResponse",
        "type": "object",
        "properties": {
          "token": {
            "type": "string",
            "description": "The user's authentication token — the value for the `X-User-Token` header,\nsent with `X-User-Email`. Long-lived; it is not reissued by\n`POST /api/v1/refresh_tokens`.\n",
            "example": "tok_abc123"
          },
          "access_token": {
            "type": "string",
            "description": "Bearer token for the `Authorization` header. Lifetime is set per API key\n(24 hours by default) when issued here.\n",
            "example": "lmn456"
          },
          "refresh_token": {
            "type": "string",
            "description": "Valid for one month, and exchanged for a new pair by `POST /api/v1/refresh_tokens`.",
            "example": "xyz890"
          }
        }
      },
      "RefreshTokensResponse": {
        "title": "RefreshTokensResponse",
        "type": "object",
        "properties": {
          "access_token": {
            "type": "string",
            "description": "Access Tokens expire 24 hours after issue",
            "example": "lmn456"
          },
          "refresh_token": {
            "type": "string",
            "example": "xyz890"
          }
        }
      }
    },
    "securitySchemes": {
      "APIKeyHeader": {
        "type": "apiKey",
        "name": "X-Api-Key",
        "in": "header",
        "description": "Server-to-server API key. Issued at one of two access levels:\n\n- **Full access** — unrestricted.\n- **Read-only** — only `GET`, `HEAD`, and `OPTIONS` requests are accepted. All other\n  methods return `403 Forbidden` with body\n  `{ \"message\": \"Read-only API keys cannot modify resources.\" }`.\n"
      },
      "UserEmailHeader": {
        "type": "apiKey",
        "name": "X-User-Email",
        "in": "header"
      },
      "UserTokenHeader": {
        "type": "apiKey",
        "name": "X-User-Token",
        "in": "header"
      },
      "oAuth2Password": {
        "type": "oauth2",
        "flows": {
          "password": {
            "tokenUrl": "https://showami.com/users/sign_in",
            "refreshUrl": "https://showami.com/api/v1/refresh_tokens",
            "scopes": {}
          }
        }
      }
    }
  },
  "x-tagGroups": [
    {
      "name": "Authentication",
      "tags": [
        "Authentication"
      ]
    },
    {
      "name": "API Endpoints",
      "tags": [
        "Showings",
        "Messages",
        "Tasks",
        "Rentals",
        "Property Data Collection",
        "Users",
        "Consumers",
        "Referrals",
        "Price Suggestions",
        "Reports"
      ]
    },
    {
      "name": "Webhook Events",
      "tags": [
        "Webhooks"
      ]
    }
  ]
}