openapi: 3.1.0
info:
  title: Zapier Integration API
  description: |
    This API enables integration between Zapier and the ShowMojo platform.
    It uses the standard OAuth 2.0 authorization flow to connect a user's ShowMojo account
    with Zapier. Authentication is required solely to link the Zapier app to the user's ShowMojo account;
    users will still log in using their ShowMojo credentials.

    Currently, the integration supports:

    - Webhook-based triggers for showing-related events
    - Action to create new property listings

    Additional actions and triggers may be added in future versions of the integration.
  version: 1.0.0
servers:
  - url: https://showmojo.com
    description: Production
  - url: https://mock-docs.showmojo.com
    description: Sandbox
  - url: http://localhost:4010
    description: Local
tags:
  - name: authentication
    description: |
      OAuth 2.0 flow for authorizing the Zapier app with a ShowMojo account. Used only during initial account connection. Clients still sign in separately.
    x-displayName: Authentication
  - name: webhook_subscriptions
    description: |
      Create and remove subscriptions to receive webhook events such as showing creation, cancellation, blacklisting, or screening denial.
    x-displayName: Webhook Subscriptions
  - name: webhook_payload
    x-displayName: Webhook Payload
    description: |
      Defines the structure of webhook payloads sent from ShowMojo to Zapier. Payloads are automatically sent to all subscribed endpoints when a matching event occurs.
  - name: showings
    description: |
      Webhook-triggered events that inform Zapier when a prospect schedules, cancels, or is blocked from a showing.
    x-displayName: Showing Events
  - name: listings
    description: |
      Endpoints to create and update property listings on the ShowMojo platform. Only create action is available at the moment.
    x-displayName: Listings
paths:
  /zapier/me:
    get:
      tags:
        - authentication
      summary: Check OAuth2 authentication
      description: |
        This endpoint is used by Zapier **once, during the OAuth2 authorization flow**, to verify that the access token works and corresponds to a valid ShowMojo account.

        It is not intended for general use or for data extraction — only as part of the automated Zapier connection process.

        ---

        ## Usage

        This endpoint is used by Zapier to:

        * Validate that the OAuth2 `access_token` is active and linked to a real account
        * Display the account `name` during login/connection flow in the Zapier UI

        No other usage is expected or supported.
      operationId: getMe
      security:
        - oauth2: []
      responses:
        '200':
          description: Authenticated account information
          content:
            application/json:
              schema:
                type: object
                properties:
                  account_id:
                    type: integer
                    description: Internal account ID
                  email:
                    type: string
                    description: Account email address
                  name:
                    type: string
                    description: Display name shown in Zapier UI
              example:
                account_id: 2
                email: multiuser@example.com
                name: Test Staging Properties
        '401':
          description: Unauthorized – Invalid or missing token
  /zapier/webhook_subscriptions:
    post:
      tags:
        - webhook_subscriptions
      summary: Create webhook subscription
      description: |
        Zapier uses these internal endpoints to manage webhook subscriptions for your ShowMojo account.
        You do **not** need to call these endpoints manually — they are configured automatically when you
        enable or disable a Zap that uses a trigger such as:

        - New Showing Scheduled
        - Showing Canceled
        - Prospect Blacklisted
        - Prospect Denied by Screening

        Each time a Zap is activated, ShowMojo receives a request to register a `target_url` for the appropriate event type.
        This URL will then receive webhook notifications automatically whenever a matching event occurs in your account.

        ---

        **Used by:** Zapier when you enable a Zap with a trigger

        Registers a new target URL to receive events of a specified type.

        ### Supported Event Types

        - `new_showing` — Triggered when a new showing is scheduled.
        - `cancel_showing` — Triggered when a showing is canceled.
        - `blacklisted_showing` — Triggered when a prospect is blacklisted.
        - `denied_showing` — Triggered when a prospect is denied based on screening criteria.
      operationId: createWebhookSubscription
      security:
        - oauth2: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - event_type
                - target_url
              properties:
                event_type:
                  type: string
                  enum:
                    - new_showing
                    - cancel_showing
                    - blacklisted_showing
                    - denied_showing
                  example: new_showing
                target_url:
                  type: string
                  format: uri
                  example: https://hooks.zapier.com/hooks/catch/XXXX/YYYY
      responses:
        '201':
          description: Subscription created
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                    example: subscription_id
  /zapier/webhook_subscriptions/{id}:
    delete:
      tags:
        - webhook_subscriptions
      summary: Delete webhook subscription
      description: |
        ## Delete Webhook Subscription

        **Used by:** Zapier when you disable or delete a Zap with a trigger

        Removes a previously registered webhook subscription so that it no longer receives events.
        Zapier calls this automatically when a Zap is turned off or deleted.

        > This response indicates that the subscription was successfully removed and will no longer receive events.
      operationId: deleteWebhookSubscription
      security:
        - oauth2: []
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
            example: 456001
      responses:
        '204':
          description: Subscription deleted
  /zapier/listings:
    post:
      tags:
        - listings
      summary: Create new listing
      description: |
        This endpoint allows Zapier to create new listings in a ShowMojo account.

        It is used exclusively by the Zapier integration and is not intended for direct use outside of Zapier.

        ---

        ## Purpose

        The endpoint is triggered when a Zap includes an action to create a listing.  
        It allows third-party platforms (such as CRMs or property management tools) to send listing data to ShowMojo through Zapier automation.

        Each request creates a **new listing** within the authenticated user's account.

        ---

        ## Field Notes

        - The `code` field serves as the client's external identifier (e.g., a property code or MLS ID).
        - The `status` must be a valid internal listing status (`STATUS_ACTIVE`, etc.).
        - The `pets` field accepts an array of strings to describe allowed pet types.

        ---

        ## Usage in Zapier

        This endpoint is automatically called by Zapier when:
        - A Zap includes the "Create Listing" action
        - The user fills in listing details during Zap configuration

        No manual configuration or direct API use is required from end users.
      operationId: createZapierListing
      security:
        - oauth2: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                listing_params:
                  type: object
                  required:
                    - address
                    - city
                    - state
                  properties:
                    code:
                      type: string
                      description: Unique identifier for the listing, typically from your internal system.
                      example: TX-HOU-3198
                    status:
                      type: string
                      description: Status of the listing (`STATUS_ACTIVE`, `STATUS_INACTIVE`, `STATUS_DELETED`).
                      example: STATUS_ACTIVE
                    address:
                      type: string
                      description: Street address of the property.
                      example: 3198 Westheimer Rd
                    unit:
                      type: string
                      description: Unit or apartment number, if applicable.
                      example: Apt 304
                    city:
                      type: string
                      description: City where the property is located.
                      example: Houston
                    state:
                      type: string
                      description: Two-letter state abbreviation.
                      example: TX
                    zip:
                      type: string
                      description: ZIP or postal code.
                      example: '77098'
                    title:
                      type: string
                      description: Listing title shown to prospects.
                      example: Modern 1BR Loft with Skyline Views and Rooftop Access
                    year_built:
                      type: integer
                      description: Year the property was built.
                      example: 2015
                    rent:
                      type: number
                      format: float
                      description: Base monthly rent amount.
                      example: 2125
                    max_rent:
                      type: number
                      format: float
                      description: Optional maximum rent for variable pricing.
                      example: 2300
                    price:
                      type: number
                      format: float
                      description: Total price of the property if it's for sale.
                      example: 315000
                    bedrooms:
                      type: integer
                      description: Number of bedrooms in the unit.
                      example: 1
                    full_bathrooms:
                      type: integer
                      description: Number of full bathrooms (with shower or tub).
                      example: 1
                    partial_bathrooms:
                      type: integer
                      description: Number of half-bathrooms (toilet and sink only).
                      example: 1
                    offices:
                      type: integer
                      description: Number of dedicated office rooms.
                      example: 1
                    square_feet:
                      type: integer
                      description: Total area in square feet.
                      example: 910
                    property_tax:
                      type: number
                      format: float
                      description: Annual property tax amount, if applicable.
                      example: 3480
                    highlights:
                      type: string
                      description: Description text highlighting amenities and location benefits.
                      example: |
                        Floor-to-ceiling windows, smart thermostat, rooftop pool, secure parking, gym access. Located in the heart of Upper Kirby, walkable to coffee shops and Whole Foods.
                    video_url:
                      type: string
                      format: uri
                      description: Public URL of a marketing video or virtual tour.
                      example: https://www.youtube.com/watch?v=dQw4w9WgXcQ
                    tour_url:
                      type: string
                      format: uri
                      description: URL to a 3D tour or external tour site.
                      example: https://www.zillow.com/view-3d-home/54321
                    security_deposit_type:
                      type: string
                      description: Type of deposit setting, `SET_AMOUNT`, `DONT_SHOW`, `MULTIPLE_RENT`, `RENT_PLUS_AMOUNT`, `NO_DEPOSIT`
                      example: SET_AMOUNT
                    security_deposit_value:
                      type: number
                      format: float
                      description: Amount of required security deposit.
                      example: 1250
                    pets:
                      type: array
                      items:
                        type: string
                      description: List of pet-related policies (e.g. Cats allowed, Small dogs only).
                      example:
                        - Cats ok
                        - Dogs ok
                    images:
                      type: array
                      items:
                        type: string
                        format: uri
                      description: List of image URLs to display in the listing gallery.
                      example:
                        - https://images.unsplash.com/photo-1580587771525-78b9dba3b914
                        - https://images.unsplash.com/photo-1560448075-bb3c2930f57b
              required:
                - listing_params
            example:
              listing_params:
                code: TX-HOU-3198
                status: STATUS_ACTIVE
                address: 3198 Westheimer Rd
                unit: Apt 304
                city: Houston
                state: TX
                zip: '77098'
                title: Modern 1BR Loft with Skyline Views and Rooftop Access
                year_built: 2015
                rent: 2125
                max_rent: 2300
                price: 315000
                bedrooms: 1
                full_bathrooms: 1
                partial_bathrooms: 1
                offices: 1
                square_feet: 910
                property_tax: 3480
                highlights: |
                  Floor-to-ceiling windows, smart thermostat, rooftop pool, secure parking, gym access. Located in the heart of Upper Kirby, walkable to coffee shops and Whole Foods.
                video_url: https://www.youtube.com/watch?v=dQw4w9WgXcQ
                tour_url: https://www.zillow.com/view-3d-home/54321
                security_deposit_type: SET_AMOUNT
                security_deposit_value: 1250
                pets:
                  - Cats allowed
                  - Small dogs only
                images:
                  - https://images.unsplash.com/photo-1580587771525-78b9dba3b914
                  - https://images.unsplash.com/photo-1560448075-bb3c2930f57b
                  - https://images.unsplash.com/photo-1618220179428-22790b461013
      responses:
        '201':
          description: Listing created successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  listing:
                    type: object
                    properties:
                      uid:
                        type: string
                        example: xyz123
                      code:
                        type: string
                        example: APT-001
                      edit_url:
                        type: string
                        format: uri
                        example: https://showmojo.com/edit/xyz123
                      public_url:
                        type: string
                        format: uri
                        example: https://showmojo.com/listing/xyz123
        '400':
          description: Missing required listing_params
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      base:
                        type: array
                        items:
                          type: string
              example:
                errors:
                  base:
                    - Please provide listing data.
        '422':
          description: Validation failed
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    additionalProperties:
                      type: array
                      items:
                        type: string
              example:
                errors:
                  base:
                    - Address can't be blank for listings for rent or sale
components:
  securitySchemes:
    oauth2:
      type: oauth2
      flows:
        authorizationCode:
          authorizationUrl: https://showmojo.com/oauth2/authorize
          tokenUrl: https://showmojo.com/oauth2/token
          scopes:
            zapier: Access to Zapier integration features
webhooks:
  Showing Event:
    post:
      tags: webhook_payload
      summary: Showing related events
      description: |
        When a showing-related event occurs in your ShowMojo account, a webhook is automatically sent to all registered `target_url`s
        that are subscribed to the matching event type. These webhooks are used to trigger Zapier automations.

        You do **not** need to configure or send these webhooks yourself — ShowMojo manages subscription delivery automatically.

        ---

        ## Event Flow

        1. A showing-related event occurs (e.g., new showing scheduled).
        2. All active webhook subscriptions for that event type are fetched from the associated account.
        3. The payload is sent to each subscriber's `target_url` via HTTPS POST.
        4. Delivery failures are automatically retried.

        ### Retry Policy

        - Up to **3 delivery attempts** are made for each webhook.
        - Retries follow an **exponentially increasing delay** (polynomial backoff).
        - If all retries fail, the event is not requeued again.

        ---

        ## Webhook Payload Format

        The webhook payload includes a single root `event` object, which contains:
        - metadata about the event itself (ID, timestamp, actor, type)
        - the associated **showing** details
        - an `action` field indicating the specific event type
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                event:
                  type: object
                  required:
                    - id
                    - action
                    - actor
                    - created_at
                  properties:
                    id:
                      type: string
                      description: Unique identifier for the event
                      example: abc-123
                    action:
                      type: string
                      enum:
                        - lead_created
                        - lead_updated
                        - showing_created
                        - showing_updated
                        - showing_canceled
                      description: Type of event
                      example: lead_created
                    actor:
                      type: string
                      description: Who initiated the event (usually `prospect` or `system`)
                      example: prospect
                    team_member_name:
                      type: string
                      nullable: true
                      example: Alex Manager
                    team_member_uid:
                      type: string
                      nullable: true
                      example: tm-001
                    created_at:
                      type: string
                      format: date-time
                      example: '2025-05-08T12:34:56Z'
                    showing:
                      type: object
                      nullable: true
                      properties:
                        uid:
                          type: string
                          example: shw-789
                        created_at:
                          type: string
                          format: date-time
                          example: '2025-05-08T12:34:56Z'
                        showtime:
                          type: string
                          format: date-time
                          example: '2025-05-09T14:00:00Z'
                        showing_time_zone:
                          type: string
                          example: Central Time (US & Canada)
                        showing_time_zone_utc_offset:
                          type: integer
                          example: -5
                        name:
                          type: string
                          example: John Doe
                        phone:
                          type: string
                          example: '+14004004444'
                        email:
                          type: string
                          format: email
                          example: john.doe@example.com
                        notes:
                          type: string
                          nullable: true
                          example: Interested in a pet-friendly unit
                        listing_uid:
                          type: string
                          example: lst-456
                        listing_full_address:
                          type: string
                          example: 123 Main St, Springfield, IL 62704
                        is_self_show:
                          type: boolean
                          example: true
                        confirmed_at:
                          type: string
                          format: date-time
                          nullable: true
                          example: '2025-05-08T13:00:00Z'
                        canceled_at:
                          type: string
                          format: date-time
                          nullable: true
                          example: null
                        self_show_code_distributed_at:
                          type: string
                          format: date-time
                          nullable: true
                          example: '2025-05-08T13:10:00Z'
      responses:
        '200':
          description: Successfully received
        '400':
          description: Bad request — malformed payload
        '401':
          description: Unauthorized — invalid or missing token
