{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/dotsy-ai/json-schema/dotsy-ai-import-site-request-schema.json",
  "title": "ImportSiteRequest",
  "description": "What to import. Only `sourceUrl` is needed: it imports every page dotsy can discover on that site.",
  "x-generated": "2026-11-06",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/dotsy-ai-openapi.yml#/components/schemas/ImportSiteRequest",
  "type": "object",
  "properties": {
    "sourceUrl": {
      "type": "string",
      "format": "uri",
      "description": "The website to import. Without `pages` and `segments`, dotsy imports the whole site it can discover from here."
    },
    "mode": {
      "type": "string",
      "enum": [
        "auto",
        "mirror",
        "render"
      ],
      "description": "Default `auto`."
    },
    "pages": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "description": "Page URL, absolute or relative to `sourceUrl`."
          },
          "key": {
            "type": "string",
            "description": "Content key to store the page under."
          },
          "mode": {
            "type": "string",
            "enum": [
              "auto",
              "mirror",
              "render"
            ],
            "description": "How a page is captured. `mirror` copies the served HTML, `render` runs the page in a browser first (for sites that build their content with JavaScript), `auto` mirrors each page and switches it to render when it looks like a JavaScript-built shell."
          }
        },
        "required": [
          "url",
          "key"
        ]
      },
      "description": "An explicit page list, taken as given. Omit it (and `segments`) to let dotsy find the pages from the sitemap and the home page links. Two pages sharing a key collapse into one, which comes back as a warning."
    },
    "segments": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "pathPrefix": {
            "type": "string",
            "description": "The part of the site this segment covers."
          },
          "sitemap": {
            "type": "string",
            "description": "Sitemap path, relative to `sourceUrl` (for example `/blog/sitemap.xml`). Without it only the segment's hub page is imported, and a `segment_hub_only` warning says so."
          },
          "mode": {
            "type": "string",
            "enum": [
              "auto",
              "mirror",
              "render"
            ],
            "description": "How a page is captured. `mirror` copies the served HTML, `render` runs the page in a browser first (for sites that build their content with JavaScript), `auto` mirrors each page and switches it to render when it looks like a JavaScript-built shell."
          },
          "maxPages": {
            "type": "integer",
            "minimum": 1,
            "description": "Cap for this segment (default 500). A larger sitemap needs an explicit higher cap."
          }
        },
        "required": [
          "pathPrefix"
        ]
      },
      "description": "For a site served from several places: each segment expands into pages through its own sitemap."
    },
    "keyConvention": {
      "type": "string",
      "enum": [
        "flat",
        "directory"
      ],
      "description": "Shape of the content keys. `directory` stores `about/index.html` (static-site output); `flat` (default) stores `about.html`."
    },
    "onSlugTaken": {
      "type": "string",
      "enum": [
        "auto-suffix",
        "fail",
        "merge"
      ],
      "description": "What to do when `{slug}` is already in use. `auto-suffix` (default): when another account holds it, import into `{slug}-{adjective}-{noun}` instead; when you own it, answer 409 `slug_taken_self`. `fail`: when another account holds it, answer 409 `slug_taken` with suggestions. `merge`: when you own it, add or update the pages on that site; when another account holds it, behaves like `auto-suffix`."
    },
    "assetMirror": {
      "type": "string",
      "enum": [
        "full",
        "same-host",
        "off"
      ],
      "description": "Which asset URLs are copied into dotsy. `full` (default): the source's own assets and the cross-origin assets they use (CDN images, fonts, scripts). `same-host`: only assets served from the source host. `off`: none, so asset URLs keep pointing at the source."
    },
    "assetWarm": {
      "type": "string",
      "enum": [
        "auto",
        "inline",
        "deferred"
      ],
      "description": "When mirrored assets are copied. `inline`: during the import. `deferred`: in a background job afterwards. `auto` (default): inline up to 100 external assets, deferred beyond."
    },
    "skipHosts": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Asset hosts to leave alone: matching URLs stay pointing at the source."
    },
    "mirrorHosts": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "With `assetMirror: full`, copy cross-origin assets only from hosts that match one of these."
    }
  },
  "required": [
    "sourceUrl"
  ]
}