---
title: "Import Website"
method: POST
path: "/api/v1/content/properties/{property_id}/import-website"
tags: ["Content Management"]
---

# Import Website

`POST /api/v1/content/properties/{property_id}/import-website`

Kick off an async website import; returns a job to poll.

The whole pipeline — crawl (~20–60s) → LLM structuring (minutes) → DB write —
is 5–7 min for a real multi-page property, which outlives browser/proxy
timeouts (the operator saw a failure while the server kept running and
eventually wrote the pages). So this endpoint does only the fast, synchronous
part inline and enqueues the slow part as a background job that owns its own
DB session, returning immediately with the job. Poll
``GET /import-website/jobs/{job_id}`` for status/progress; pages land as
reviewable DRAFTs when it completes.

Inline verification (a guide belongs to one property): the pasted URL's
registrable domain must match the property's verified website (its stored
`website_url`, else Google Maps' `websiteUri` for a linked place). A mismatch
is a hard block (422) — a user cannot pour an unrelated site into a property's
knowledge base.

Single in-flight per property+source: a re-import (e.g. a client-abort retry)
while a job for the same canonical URL is still running returns that same job
instead of starting a concurrent duplicate.

## Path parameters

- `property_id` string, uuid, required

## Request body

- ImportWebsiteRequest
  - `url` string, required
  - `content_type` 'general' | 'dining'

## Response `202`

Successful Response

- WebsiteImportJobRead — Pollable status of an async website-import job (see ``WebsiteImportJob``). Returned by the ``/import-website`` kickoff and its status endpoint. The operator polls ``status`` (and ``sources_done``/``sources_total`` during structuring); ``result`` is populated once ``status == "completed"``, and ``error_message`` carries a human-readable reason once ``status == "failed"``.
  - `id` string, uuid, required
  - `property_id` string, uuid, required
  - `status` 'queued' | 'crawling' | 'structuring' | 'completed' | 'failed', required — Lifecycle of an async website-import job (see ``WebsiteImportJob``). A real multi-page property import takes 5–7 min (crawl + LLM structuring), which outlives client/proxy timeouts, so the work runs on the arq worker and the operator polls this status. QUEUED → CRAWLING → STRUCTURING → COMPLETED, or → FAILED at any point with a human-readable ``error_message``.
  - `url` string, required
  - `source_ref` string, required
  - `content_type` string, required
  - `source_pages_crawled` integer, nullable
  - `sources_total` integer, nullable
  - `sources_done` integer
  - `error_message` string, nullable
  - `result` DocumentImportResult — What the import did, surfaced to the hotelier for review.
    - `imported` string[]
    - `skipped_manual_pages` string[]
    - `overwritten_human_edits` string[]
    - `removed_stale_pages` string[]
    - `retained_edited_pages` string[]
  - `created_at` string, date-time, required
  - `updated_at` string, date-time, required
  - `started_at` string, date-time, nullable
  - `completed_at` string, date-time, nullable

## Other responses

- `400` — Invalid or unreachable URL.
- `404` — Property not found.
- `422` — URL doesn't match this property's verified website.
- `503` — Could not start the import. Please try again.

---

[API](https://skmtc.dev/getanana/apis/cleon-api.md) · [All operations](https://skmtc.dev/getanana/apis/cleon-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/getanana/cleon-api/revisions/a9141b6e4e7e/schema)
