Vizit Public APIAPI
Exports

Retrieve an export

Poll for the status of a previously submitted export, and download once ready.

GET/v1/exports/{export_id}

Returns the current status of an export job. When status is COMPLETED and the artifact has not yet expired, download_url is populated with a path to Download an export artifact. Authenticate that follow-up GET with the same Bearer token used for this endpoint — the URL itself does not carry embedded credentials.

Lifecycle:

  • PENDING / PROCESSINGdownload_url is null, no error_code
  • COMPLETED (within retention) → download_url populated
  • COMPLETED (past 7-day retention) → download_url is null, error_code: EXPORT_EXPIRED
  • ERRORdownload_url is null, error_code: EXPORT_FAILED

Cross-org access is intentionally indistinguishable from "not found"; foreign export_ids return 404 EXPORT_NOT_FOUND.

Authorization

bearerAuth
Authorization<token>

Short-lived access token issued by Create a token. Send it on every request as Authorization: Bearer <token>.

In: header

Path Parameters

export_id*string

The export_id returned by Create a bulk export job.

Formatuuid

Response Body

application/json

application/json

curl -X GET "https://ext.vizit.com/v1/exports/497f6eca-6276-4993-bfeb-53cbbbba6f08"
{  "export_id": "a9a55f8d-48b1-4a5b-a88e-c41b0cd75102",  "subject": "pdps",  "status": "PENDING",  "requested_at": "2019-08-24T14:15:22Z",  "completed_at": "2019-08-24T14:15:22Z",  "row_count": 0,  "byte_size": 0,  "download_url": "string",  "download_url_expires_at": "2019-08-24T14:15:22Z",  "expires_at": "2019-08-24T14:15:22Z",  "error_code": "string"}
Empty
{  "detail": "string",  "status_code": 0,  "error_code": "INVALID_GTIN",  "request_id": "266ea41d-adf5-480b-af50-15b940c2b846",  "extra": {    "failed_urls": [      {        "url": "https://cdn.example.com/broken.jpg",        "reason": "IMAGE_DOWNLOAD_TIMEOUT"      },      {        "url": "https://cdn.example.com/icon.svg",        "reason": "UNSUPPORTED_IMAGE_FORMAT"      }    ]  },  "timestamp": "2019-08-24T14:15:22Z"}

POSTCreate a bulk export job

Queues an asynchronous bulk export for the caller's organization. The response returns immediately with `status: PENDING` and a `status_url` pointing at [Retrieve an export](/api/exports/getExport); poll there until `status` reaches `COMPLETED` to obtain the short-lived presigned download URL. Org scope is enforced by the access token; the optional `filters` block narrows within the org. Each caller is limited to one in-flight `PENDING`/`PROCESSING` export at a time — additional submissions return `409 EXPORT_CONCURRENCY_LIMIT`. ## CSV format Exports are CSV in v1 (JSONL and Parquet deferred to v2). The header row is fixed per `subject`; carousel rows in `subject=images` exports emit empty values for hero-only columns so partners can rely on a stable column set. ### `subject=pdps` column set | Column | Type | Notes | | --- | --- | --- | | `pdp_id` | uuid | PDP identifier; stable across refreshes | | `portfolio_id` | uuid | Owning portfolio | | `retailer_region` | string | e.g. `amazon_us`, `walmart_us` | | `item_id` | string | ASIN or GTIN, depending on retailer | | `name` | string \| null | PDP display name | | `brand` | string \| null | | | `category_id` | uuid \| null | Vizit category identifier | | `category` | string \| null | Category display name | | `listing_score` | int \| null | 0–100, resolved per org | | `raw_listing_score` | float \| null | Pre-blend, pre-penalty | | `listing_score_blended` | int \| null | 0–100, pre-penalty | | `score_penalty` | bool \| null | True if any penalty applied | | `image_count_penalty` | float \| null | | | `image_mix_penalty` | float \| null | | | `image_order_penalty` | float \| null | | | `high_scoring_asset_count` | int \| null | | | `is_ideal_content_mix` | bool \| null | | | `images_matching_ideal_mix` | int \| null | | | `score_status` | string | `CREATED`, `PROCESSING`, `SCORED`, or `CATEGORY_NOT_FOUND` | | `created_at` | date-time | | | `updated_at` | date-time | | | `last_refreshed` | date-time \| null | Last successful scrape + score | ### `subject=images` column set Hero-score and mobile-readiness columns are populated only for hero rows; carousel rows emit empty values in those columns. | Column | Type | Notes | | --- | --- | --- | | `image_id` | uuid | | | `pdp_id` | uuid | Parent PDP | | `portfolio_id` | uuid | Denormalized from PDP for row-standalone exports | | `retailer_region` | string | | | `item_id` | string | ASIN or GTIN of the parent PDP | | `image_type` | string | `hero` or `carousel` | | `image_url` | string | | | `position` | int | 1-based position within the PDP (matches `CarouselImageResponse.position`) | | `source` | string \| null | e.g. `scraped` | | `vizit_score` | int \| null | 0–100, resolved per org | | `raw_score` | float \| null | | | `hero_score` | int \| null | 0–100; null for carousel rows. The `hero_score_breakdown` sub-scores (heroism, category_edge, technical_integrity, local_support) are intentionally omitted from v1 — the hero formula is in flight | | `mobile_ready` | bool \| null | All five clarity scores ≥ 80. Null for carousel | | `mobile_brand_clarity` | float \| null | Null for carousel | | `mobile_product_type_clarity` | float \| null | Null for carousel | | `mobile_variant_clarity` | float \| null | Null for carousel | | `mobile_count_clarity` | float \| null | Null for carousel | | `mobile_size_clarity` | float \| null | Null for carousel | | `mobile_scored_model` | string \| null | Null for carousel | | `classification` | string \| null | e.g. `Lifestyle`, `Packshot` | | `classification_confidence` | float \| null | 0–1 | | `classification_high_confidence` | bool \| null | | | `created_at` | date-time | | | `updated_at` | date-time | | | `scored_at` | date-time \| null | Last successful score |

GETDownload an export artifact

Streams the CSV artifact for a `COMPLETED` export. Uses the same Bearer token as every other endpoint — no presigned URL, no embedded credentials. The path itself is what `download_url` on [Retrieve an export](/api/exports/getExport) points at. Response shape: - `Content-Type: text/csv` - `Content-Disposition: attachment; filename="<subject>-<timestamp>.csv"` - Body is the raw CSV (header row + data rows, UTF-8, `\n` line separator) Returns `404` with a typed `error_code` for every error state — cross-org access is intentionally indistinguishable from a missing or expired export so foreign `export_id`s never leak existence: - `EXPORT_NOT_FOUND` — does not exist in the caller's org - `EXPORT_NOT_READY` — exists but `status` is still `PENDING` or `PROCESSING` - `EXPORT_EXPIRED` — artifact has been purged past its 7-day retention