Vizit Public APIAPI
Guides

Ingest a PDP

End-to-end walkthrough for submitting Amazon ASINs or GTIN-identified products and retrieving Vizit scores.

Guides

Vizit exposes two purpose-built PDP ingestion endpoints. Both follow the same shape — PUT /v1/pdps/{identifier_type}/{value} to submit, GET the same path to poll — but they serve different integration patterns. This guide walks each end-to-end and lays out the error catalog and rate-limit posture you should plan around.

Prerequisites

Before any of the requests below will succeed, make sure you have:

  • Client credentials provisioned by Vizit for your organization and target environment (production, or dev1dev5).
  • A Bearer token obtained via the OAuth 2.0 client-credentials flow described in Authentication. Cache it until expiry — tokens are valid for 24 hours.
  • A request ID strategy. Send X-Request-Id on each request to correlate your logs with Vizit's. If you omit it, Vizit generates one and echoes it on the response.

All examples below assume $BASE_URL is the environment-appropriate hostname (e.g., https://ext.vizit.com) and $TOKEN is your current access token.

Choose the right endpoint

You want…Endpoint pairWhat you send
Vizit to scrape Amazon for you and score the result/v1/pdps/asin/{asin}Just the ASIN (and optionally a regional Amazon storefront)
To push your own image URLs and metadata (PIM-style integrations like Syndigo or Salsify)/v1/pdps/gtin/{gtin}GTIN plus your hero / carousel image URLs and a product_category_id

Both flows return 202 Accepted immediately. Scoring runs asynchronously; clients poll GET until status transitions from "processing" to "scored".

One identifier per endpoint

Don't try to submit the same product to both endpoints. The ASIN flow scrapes Amazon to get its own image set; the GTIN flow stores the images you provide. Mixing them creates duplicate PDPs in your organization's library.

Walkthrough: scrape an Amazon ASIN

The scraped-content flow is built for services teams onboarding a customer's ASIN catalog and for partner workflows that want Vizit scores across a target brand's listings without managing images themselves.

1. Submit the ASIN

curl -X PUT "$BASE_URL/v1/pdps/asin/B07XVTRJKX" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"region": "us"}'

Path parameter and body:

FieldTypeRequiredDefaultNotes
asin (path)stringYesMust match ^[A-Z0-9]{10}$ exactly. Lowercase or wrong-length values return 400 INVALID_ASIN without a retailer call.
regionstringNo"us"Amazon storefront region. Common values: us, uk, de, ca. Unsupported values return 400 INVALID_REGION.

Successful response (202 Accepted):

{
  "asin": "B07XVTRJKX",
  "region": "us",
  "pdp_id": "9b0a0c4e-3c1d-4b9e-9f08-2c7e3a1f1d77",
  "status": "processing",
  "score_url": "/v1/pdps/asin/B07XVTRJKX?region=us"
}

score_url is the URL you poll next — it includes the region so you don't have to remember the storefront the PDP was ingested under.

Submitting an ASIN that's already in your library refreshes it (re-scrapes and re-scores) rather than rejecting the request, the same behavior as the in-product refresh button.

2. Poll for scores

curl "$BASE_URL/v1/pdps/asin/B07XVTRJKX?region=us" \
  -H "Authorization: Bearer $TOKEN"

While the pipeline is in flight, the response carries status: "processing" and the score fields are null. Once scoring lands, status flips to "scored", scored_at is populated, and the full payload is available:

{
  "asin": "B07XVTRJKX",
  "region": "us",
  "pdp_id": "9b0a0c4e-3c1d-4b9e-9f08-2c7e3a1f1d77",
  "status": "scored",
  "name": "Example Product",
  "category": "Fish Oil Supplements",
  "pdp_score": 67,
  "carousel_score": 52.4,
  "hero": {
    "image_id": "...",
    "image_url": "https://...",
    "hero_score": 72.0,
    "score_breakdown": { "...": "..." },
    "classification": "Packshot"
  },
  "carousel_images": [
    { "image_id": "...", "position": 1, "vizit_score": 55.0, "classification": "Lifestyle" }
  ],
  "asset_mix": { "total_images": 4, "by_classification": { "Packshot": 1, "Lifestyle": 2, "Feature Highlight": 1 } },
  "scored_at": "2026-05-13T19:42:10Z"
}

End-to-end latency for a typical Amazon ASIN is on the order of tens of seconds, capped by the scrape and scoring pipeline rather than the API layer. A polling interval of 15–30 seconds balances time-to-first-result against request volume.

If the PDP is being refreshed and a prior snapshot exists, the response returns the prior scores alongside status: "processing" so your consumers can keep using the existing data while new scoring runs.

Walkthrough: submit a GTIN with your own images

The caller-supplied-content flow is built for PIM partners pushing their own image sets — Syndigo, Salsify, in-house systems — where Vizit's job is to score the assets you provide, not to scrape a retailer.

1. Discover a product category

GTIN submissions require a product_category_id. Pull the valid IDs once and cache them:

curl "$BASE_URL/v1/product-categories" \
  -H "Authorization: Bearer $TOKEN"

The ASIN flow doesn't need this — categories are inferred server-side from the scrape.

2. Submit the PDP

curl -X PUT "$BASE_URL/v1/pdps/gtin/00012345678905" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "hero_image_url": "https://your-cdn.example.com/products/abc/hero.jpg",
    "carousel_image_urls": [
      "https://your-cdn.example.com/products/abc/carousel1.jpg",
      "https://your-cdn.example.com/products/abc/carousel2.jpg"
    ],
    "product_category_id": "5b1a7c30-7e9b-4f23-9b6f-8c12a18d3a40",
    "name": "Example Product",
    "retailer": "amazon_us"
  }'

Vizit downloads the images server-side, stores them, and kicks off the standard scoring pipeline. GTINs accept 8, 12, 13, or 14-digit values.

Successful response (202 Accepted):

{
  "gtin": "00012345678905",
  "pdp_id": "...",
  "status": "processing",
  "score_url": "/v1/pdps/gtin/00012345678905"
}

3. Poll for scores

Same pattern as ASIN. The response shape mirrors /v1/pdps/asin/{asin} with gtin instead of asin and external_id instead of region.

curl "$BASE_URL/v1/pdps/gtin/00012345678905" \
  -H "Authorization: Bearer $TOKEN"

Error cheat sheet

Every non-2xx response follows the standard error shape: error_code, detail, status_code, request_id. Branch on error_code, never on detail.

Validation errors (400)

error_codeEndpointWhat it meansLikely caller action
INVALID_ASINASINASIN doesn't match ^[A-Z0-9]{10}$.Uppercase and validate the format before sending. Don't retry the same value.
INVALID_REGIONASINThe body's region isn't a supported Amazon storefront.Use one of the documented region codes (us, uk, de, ca, …).
INVALID_GTINGTINGTIN isn't 8/12/13/14 digits.Validate format before sending.
INVALID_RETAILERGTINThe retailer value isn't a supported retailer_region key.Use amazon_us (default) or another documented retailer region.
CATEGORY_NOT_IN_ORG_ICPASIN, GTINThe product's category isn't in your organization's ICP (Ideal Customer Profile) configuration.Confirm category coverage with Vizit; this PDP can't be scored under the current configuration.
NO_VALID_CATEGORYASINThe retailer scrape didn't yield a category Vizit could resolve.Vizit logs the gap automatically; retry later if the category coverage is updated.
TOO_MANY_IMAGES (413)GTINcarousel_image_urls exceeded 20 entries.Trim the carousel to 20 or fewer URLs.
IMAGE_DOWNLOAD_FAILEDGTINOne or more submitted image URLs couldn't be fetched. extra.failed_urls lists each {url, reason}.Inspect extra.failed_urls and fix the source URLs (auth-expired, 404, wrong content-type, etc.).

Resource errors (404)

error_codeWhenWhat to do
ASIN_NOT_FOUND_AT_RETAILERThe ASIN couldn't be resolved at the retailer.Verify the ASIN exists on the target storefront. Don't retry the same value.
PDP_NOT_FOUNDGET for a PDP your organization hasn't ingested (or that lives in a different region).Check the region query parameter for ASIN GETs; for GTIN GETs, confirm the PDP was previously PUT under the same organization.

Auth and rate-limit errors

StatusHeader / CodeAction
401 UnauthorizedRequest a fresh access token and retry once. See Authentication.
403 ForbiddenThe token is valid but doesn't have permission for this resource. Contact Vizit.
429 Too Many RequestsRetry-After headerBack off for Retry-After seconds, then resume. Use exponential backoff for repeated 429s.

Upstream errors (5xx)

error_codeStatusWhat to do
SCRAPE_TIMEOUT504Retailer scrape timed out. Retry with exponential backoff.
SCRAPE_UPSTREAM_ERROR502Retailer scrape failed. Retry with exponential backoff; if it persists for hours, contact Vizit.

See Errors for the full shared error format and HTTP status reference.

Rate limits and retries

  • Per-organization rate limits are enforced at the API gateway. The exact tier is set when Vizit provisions your credentials; treat a dozen submissions per minute per organization as a safe baseline unless you've been told otherwise.
  • Exceeding the limit returns 429 Too Many Requests with a Retry-After header.
  • Retry 429 and 5xx responses with exponential backoff (start at ~5s, double on each retry, cap at ~60s).
  • Do not retry 4xx responses other than 429 until you've fixed the underlying request — the same input will fail the same way.

What's next

On this page