openapi: 3.1.0
info:
  title: JumpSites Agentic Site Builder
  version: 1.0.0
  description: >-
    Build a live, hosted website preview for a local contractor, handyman, or
    trade business from minimal information. An AI agent supplies the business
    name, trade, and location; JumpSites writes the copy, builds the site, and
    returns a preview URL the business owner can review and publish.


    Agent Decision Tree (use the first path you are able to execute):


    1. Can you call createIntake? Use POST /api/intake. This is the preferred
    automated workflow — JumpSites builds the site and returns a previewUrl.

    2. Cannot call createIntake, but can call createSiteDeepLink? Use POST
    /api/deeplink. JumpSites returns a fully prefilled, user-facing URL — give
    it directly to the user.

    3. Cannot call any JumpSites API? Construct the JumpSites deep link locally
    using the x-deeplink template below. No API call is required — give the
    resulting URL directly to the user.


    All three paths use the same business vocabulary, so collect the information
    once and route it through whichever integration path is available. The
    deep-link paths preserve collected information and are intended to prevent
    users from re-entering business details.
  x-deeplink:
    description: Universal fallback for agents without API access. When you cannot
      call any JumpSites endpoint, construct this URL yourself and provide it
      directly to the user. Opening the link continues the JumpSites onboarding
      and build flow with all supplied information prefilled.
    urlTemplate: https://app.pros.jumpsites.co/build?business={business}&trade={trade}&city={city}&address={address}&phone={phone}&email={email}&googleBusinessUrl={googleBusinessUrl}&services={comma,separated,slugs}&templateId={templateId}&utm_source={utm_source}&utm_medium={utm_medium}&utm_campaign={utm_campaign}
    rules:
      - Only business, trade, and city are required for a useful build.
      - Omit parameters that are unknown rather than sending empty values.
      - URL-encode every value.
      - services is a comma-separated list using the same service slugs accepted
        by createSite.
      - templateId must be one of template-1-professional, template-2-friendly,
        template-3-clinical, or template-4-modern.
      - If templateId is omitted, JumpSites defaults to template-1-professional.
      - Set utm_source to the assistant name when known.
      - businessName maps to business.
      - businessType and specialty map to trade.
      - location may map to city.
    assistantConstructionExample:
      input:
        business: Joe's Plumbing
        trade: plumber
        city: Austin, TX
      output: https://app.pros.jumpsites.co/build?business=Joe%27s%20Plumbing&trade=plumber&city=Austin%2C%20TX&utm_source=chatgpt
    example: https://app.pros.jumpsites.co/build?business=Joe%27s%20Plumbing&trade=plumber&city=Austin%2C%20TX&services=plumbing,emergency-repairs&templateId=template-1-professional&utm_source=chatgpt
servers:
  - url: https://api.pros.jumpsites.co
    description: Production API.
paths:
  /api/ai/site:
    post:
      operationId: createSite
      summary: Create a website preview for a local trade business
      description: Generate a hosted website preview for a local trade business
        (contractor, plumber, electrician, handyman, roofer) from minimal
        details. Before calling, show the user the four template styles (see
        templateId) and ask which they want. Returns a previewUrl to open and
        publish. If this operation cannot be executed, construct a JumpSites
        deep link using the template documented in the API description and
        provide that URL to the user.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateSiteRequest"
            examples:
              plumber:
                summary: Plumber (minimal required fields)
                value:
                  businessName: Joe's Plumbing
                  businessType: plumber
                  city: Austin, TX
              electrician:
                summary: Electrician with services and template
                value:
                  businessName: Bright Electric
                  businessType: electrician
                  city: Denver, CO
                  services:
                    - electrical
                    - emergency-repairs
                  templateId: template-1-professional
              handyman:
                summary: Handyman with contact details
                value:
                  businessName: Happy Handyman
                  businessType: handyman
                  city: Portland, OR
                  phone: 503-555-0100
                  email: hello@happyhandyman.example
                  services:
                    - general-handyman
                    - assembly-installation
                    - carpentry-trim
      responses:
        "200":
          description: Site preview created.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CreateSiteResponse"
              example:
                ok: true
                previewUrl: https://app.pros.jumpsites.co/start?draft=550e8400-e29b-41d4-a716-446655440000
                editUrl: https://app.pros.jumpsites.co/start?draft=550e8400-e29b-41d4-a716-446655440000
                draftToken: 550e8400-e29b-41d4-a716-446655440000
                template: template-1-professional
                expiresInHours: 24
        "422":
          description: Validation error (missing or invalid fields).
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "429":
          description: Rate limited.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "500":
          description: Internal error while building the site.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
  /api/intake:
    post:
      operationId: createIntake
      summary: Build or stage a website from business details (transport-agnostic
        intake)
      description: >-
        PREFERRED automated build path.


        Accepts the same external vocabulary used by JumpSites deep links and
        returns either:

        - readiness='ready' with previewUrl and draftToken

        - readiness='needs_review' with the missing fields


        This endpoint is intended for AI assistants, MCP tools, partner
        integrations, and programmatic workflows.


        If this operation cannot be executed (unsupported action, unavailable
        network access, endpoint restrictions, permission gating, or environment
        limitations): use createSiteDeepLink if available, otherwise construct a
        JumpSites deep link using the x-deeplink template documented in the API
        description. Agents should not ask users to re-enter information that
        has already been collected.


        This operation shares the same vocabulary as createSiteDeepLink and
        locally constructed JumpSites deep links.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/IntakeRequest"
            examples:
              plumber:
                summary: Plumber (minimal required fields)
                value:
                  business: Joe's Plumbing
                  trade: plumber
                  city: Austin, TX
                  utm_source: chatgpt
              electrician:
                summary: Electrician with services and template
                value:
                  business: Bright Electric
                  trade: electrician
                  city: Denver, CO
                  services:
                    - electrical
                    - emergency-repairs
                  templateId: template-1-professional
                  utm_source: claude
              handyman:
                summary: Handyman, services as comma-separated string
                value:
                  business: Happy Handyman
                  trade: handyman
                  city: Portland, OR
                  phone: 503-555-0100
                  services: general-handyman,assembly-installation,carpentry-trim
      responses:
        "200":
          description: Either a built preview (readiness 'ready') or a staged intake
            (readiness 'needs_review').
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/IntakeResponse"
              examples:
                ready:
                  summary: Built — preview ready
                  value:
                    ok: true
                    readiness: ready
                    previewUrl: https://app.pros.jumpsites.co/start?draft=550e8400-e29b-41d4-a716-446655440000
                    editUrl: https://app.pros.jumpsites.co/start?draft=550e8400-e29b-41d4-a716-446655440000
                    draftToken: 550e8400-e29b-41d4-a716-446655440000
                    template: template-1-professional
                    attribution:
                      source: chatgpt
                    expiresInHours: 24
                needs_review:
                  summary: Not enough info — fields still needed
                  value:
                    ok: true
                    readiness: needs_review
                    data:
                      business: Just A Name
                    missing:
                      - trade
                      - city
        "429":
          description: Rate limited.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "500":
          description: Internal error while building the site.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
  /api/deeplink:
    post:
      operationId: createSiteDeepLink
      summary: Get a prefilled JumpSites link for the user (handoff fallback)
      description: "FALLBACK / user-handoff path. Use this when you cannot run the
        automated build (createIntake / createSite) — for example the action is
        unsupported in your environment, the endpoint is unavailable, or the
        build call is blocked by permissions. Returns a `deeplink`: a
        user-facing JumpSites URL with the business info already filled in. Give
        that link directly to the user; when they open it JumpSites continues
        the build in the browser with no re-entry. Accepts the same business
        intake fields as createIntake, so collect the info once and pass it
        here. This operation is side-effect-free (it only assembles a URL; it
        does not build, store, or charge anything). Always returns a usable
        link, even with partial info — anything missing is requested on the
        JumpSites screen the link opens. Attribution fields (utm_source,
        utm_medium, utm_campaign) are carried through. NOTE: this is itself a
        JumpSites API call — if you cannot reach the API at all, do not call
        this; construct the link locally using the x-deeplink template in the
        API description instead."
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/IntakeRequest"
            examples:
              plumber:
                summary: Plumber (minimal required fields)
                value:
                  business: Joe's Plumbing
                  trade: plumber
                  city: Austin, TX
                  utm_source: chatgpt
              electrician:
                summary: Electrician with services and template
                value:
                  business: Bright Electric
                  trade: electrician
                  city: Denver, CO
                  services:
                    - electrical
                    - emergency-repairs
                  templateId: template-1-professional
                  utm_source: claude
              handyman:
                summary: Handyman with contact details
                value:
                  business: Happy Handyman
                  trade: handyman
                  city: Portland, OR
                  phone: 503-555-0100
                  services:
                    - general-handyman
                    - assembly-installation
      responses:
        "200":
          description: A prefilled JumpSites deep link the agent can hand to the user.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/DeepLinkResponse"
              example:
                ok: true
                deeplink: https://app.pros.jumpsites.co/build?business=Joe%27s%20Plumbing&trade=plumber&city=Austin%2C%20TX&utm_source=chatgpt
                message: Open this link to continue building your site.
        "429":
          description: Rate limited.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "500":
          description: Internal error while assembling the link.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
components:
  schemas:
    IntakeRequest:
      type: object
      description: >-
        External intake vocabulary shared across all JumpSites integration
        paths.


        Used by createIntake, createSiteDeepLink, and locally constructed
        JumpSites deep links. Agents should collect this information once and
        route it through whichever integration path is available.


        Business + trade + (city or address) are sufficient for immediate site
        generation. Additional fields improve the generated website but are
        optional.
      properties:
        business:
          type: string
          description: Business name.
          example: Joe's Plumbing
        trade:
          type: string
          description: Trade / business type.
          example: plumber
        city:
          type: string
          description: City and (optionally) state.
          example: Austin, TX
        address:
          type: string
          description: Full street address; an alternative to city for location.
        phone:
          type: string
          description: Optional business phone.
        email:
          type: string
          description: Optional contact email.
        googleBusinessUrl:
          type: string
          description: Optional Google Business / Google Maps URL (google.com or
            maps.google.com HTTPS). If provided, the site is enriched with
            hours, address, and reviews.
        services:
          description: Service slugs (same enum as createSite). Accepts an array or a
            comma-separated string.
          oneOf:
            - type: array
              items:
                type: string
            - type: string
              description: Comma-separated service slugs.
        templateId:
          type: string
          description: Visual template id (same options as createSite). If omitted or
            unrecognized, defaults to template-1-professional.
          enum:
            - template-1-professional
            - template-2-friendly
            - template-3-clinical
            - template-4-modern
        utm_source:
          type: string
          description: Acquisition source, e.g. 'chatgpt'. 'source' or 'ref' are also
            accepted.
        utm_medium:
          type: string
          description: Acquisition medium.
        utm_campaign:
          type: string
          description: Acquisition campaign.
    IntakeResponse:
      type: object
      properties:
        ok:
          type: boolean
          example: true
        readiness:
          type: string
          enum:
            - ready
            - needs_review
          description: "'ready' responses include previewUrl/draftToken; 'needs_review'
            responses include `missing`."
        previewUrl:
          type: string
          description: Present when readiness is 'ready'. Valid for 24 hours.
        editUrl:
          type: string
          description: Present when readiness is 'ready' (same as previewUrl).
        draftToken:
          type: string
          description: Present when readiness is 'ready'.
        template:
          type: string
          description: The template the site was built with (readiness 'ready').
        data:
          type: object
          description: Present when readiness is 'needs_review' — hydrated partial
            onboarding payload.
          additionalProperties: true
        missing:
          type: array
          items:
            type: string
          description: Present when readiness is 'needs_review' — required fields still
            needed before building.
        attribution:
          type: object
          description: Normalized acquisition attribution echoed back (source, medium,
            campaign, raw params).
          additionalProperties: true
        expiresInHours:
          type: integer
          example: 24
    DeepLinkResponse:
      type: object
      properties:
        ok:
          type: boolean
          example: true
        deeplink:
          type: string
          description: User-facing JumpSites URL with the business info prefilled. Give
            this directly to the user; opening it continues the build in the
            browser with no re-entry.
          example: https://app.pros.jumpsites.co/build?business=Joe%27s+Plumbing&trade=plumber&city=Austin%2C+TX&utm_source=chatgpt
        message:
          type: string
          description: Short, user-ready instruction to surface alongside the link.
          example: Open this link to continue building your site.
    CreateSiteRequest:
      type: object
      required:
        - businessName
        - businessType
        - city
      properties:
        businessName:
          type: string
          description: The business name, e.g. "Joe's Plumbing".
          example: Joe's Plumbing
        businessType:
          type: string
          description: The kind of trade business, e.g. plumber, handyman, electrician,
            contractor, roofer.
          example: plumber
        city:
          type: string
          description: City and (optionally) state the business serves.
          example: Austin, TX
        phone:
          type: string
          description: Optional business phone number.
          example: 512-555-0100
        email:
          type: string
          description: Optional contact email.
          example: joe@example.com
        googleBusinessUrl:
          type: string
          description: Optional Google Business / Google Maps URL. If provided, JumpSites
            enriches the site with the business's hours, address, and reviews.
            Must be a google.com or maps.google.com HTTPS URL.
          example: https://maps.google.com/?cid=1234567890
        services:
          type: array
          description: Optional list of 3-6 service slugs to feature. If omitted,
            JumpSites infers services from the business type.
          items:
            type: string
            enum:
              - assembly-installation
              - basement-remodel
              - carpentry-trim
              - commercial-construction
              - decks-patios
              - doors-windows
              - drywall-painting
              - electrical
              - emergency-repairs
              - fencing-gates
              - flooring
              - general-handyman
              - kitchen-bath-remodel
              - plumbing
              - roofing-gutters
              - siding-exterior
              - tenant-improvements
              - water-damage-remediation
              - whole-home-renovation
        templateId:
          type: string
          description: Visual template for the site. Present all four styles below to the
            user and ask which they prefer BEFORE calling this operation, then
            pass their choice. Only omit this if the user explicitly declines to
            choose (defaults to template-1-professional).
          enum:
            - template-1-professional
            - template-2-friendly
            - template-3-clinical
            - template-4-modern
          x-enum-descriptions:
            template-1-professional: Clean, crisp, trust-building blue.
            template-2-friendly: Bold black & gold contractor look.
            template-3-clinical: Warm earthy handyman tones.
            template-4-modern: Professional navy & amber, suburban feel.
    CreateSiteResponse:
      type: object
      properties:
        ok:
          type: boolean
          example: true
        previewUrl:
          type: string
          description: URL the user opens to view the generated site. Valid for 24 hours.
          example: https://app.pros.jumpsites.co/start?draft=550e8400-e29b-41d4-a716-446655440000
        editUrl:
          type: string
          description: URL to continue editing the draft (same as previewUrl).
        draftToken:
          type: string
          description: Opaque token identifying the generated draft.
        template:
          type: string
          description: The template the site was built with.
        expiresInHours:
          type: integer
          description: How long the preview/draft remains available.
          example: 24
    ErrorResponse:
      type: object
      properties:
        ok:
          type: boolean
          example: false
        error:
          type: string
          description: Machine-readable error code.
          example: validation_error
        message:
          type: string
          description: Human-readable error message.
