API
esc

Type to search.

API reference

Exports

The catalogue read out for a PIM or DAM: one row per product with every asset we hold for it, signed URLs included. Read it live, ask for what changed, or freeze a selection into a file.

The ExportRow object

One product and every asset we hold for it. for product in rows: upsert product; for asset in assets: upsert asset is the whole PIM sync loop.

Attributes

  • productobject
    Show child attributesHide child attributes
    • idstring
      Crockford-base32 ULID (26 chars).
    • referencestring
    • namestring
    • sexenum, nullable
      • male
      • female
      • other
      • kid
    • deleted_attimestamp, nullable
      Set only in delta mode (since=), for a product deleted since then. Remove it on your side; its assets is empty.
  • assetsarray of objects
    Every asset we hold for the product, one entry each. Empty when nothing matches the role filter, or when the product is deleted.
    Show child attributesHide child attributes
    • idstring
      Image id — the same id GET /v1/images/{id} accepts, so one expired URL can be re-fetched without re-running the export.
    • roleenum
      • source
      • beautifier
      • tryon
      • recoloring
    • urlstring (URL)
      Time-limited signed URL to the bytes we hold for this asset (the active version, watermarked when your plan applies one).
    • url_expires_attimestamp
      RFC 3339 / ISO 8601 timestamp.
    • mime_typeenum
      • image/jpeg
      • image/png
      • image/webp
    • widthinteger, nullable
    • heightinteger, nullable
    • ai_generatedboolean
      False only for your own photos. Provided for EU AI Act labelling obligations.
    • watermarkedboolean
      The bytes behind url carry a watermark. This can change for a stable id when your plan changes; cache accordingly.
    • derivedboolean
      The asset is an edit of a generation rather than the generation itself.
    • created_attimestamp
      When the bytes were produced (task completion for generations, upload time for your photos).
    • task_idstring, nullable
      The task that produced it, for GET /v1/tasks/{id}. Null for your photos and for generations made in the dashboard.
    • attributesmap
      Per-role facts, flat and open: orientation (source), angle_shot, background, model_id (tryon), edit_number (derived). Ignore keys you do not know; new ones appear without a version bump.
    • also_featuresarray of strings
      Other products visible in this asset (tryon stylings). The asset is listed once, under the product it was made for; fan it out to these pages if your merchandising wants it there too.
    • suggested_filenamestring
      A filename (never a path) built from your export naming template, with the real extension of the bytes.

The ExportRow object

{
  "product": {
    "id": "01HX5K2MZ7A3Q4FBNDC0EVDXY1",
    "reference": "TEE-SAGE-001",
    "name": "Crewneck Tee — Sage",
    "sex": "male",
    "deleted_at": "2026-04-27T14:32:00Z"
  },
  "assets": [
    {
      "id": "01HX5K2MZ7A3Q4FBNDC0EVDXY1",
      "role": "source",
      "url": "https://example.com/…",
      "url_expires_at": "2026-04-27T14:32:00Z",
      "mime_type": "image/jpeg",
      "width": 1,
      "height": 1,
      "ai_generated": true,
      "watermarked": true,
      "derived": true,
      "created_at": "2026-04-27T14:32:00Z",
      "task_id": "01HX5K2MZ7A3Q4FBNDC0EVDXY1",
      "attributes": {
        "orientation": "front"
      },
      "also_features": [
        "01HX5K2MZ7A3Q4FBNDC0EVDXY1"
      ],
      "suggested_filename": "TEE-SAGE-001_front_cleaned.webp"
    }
  ]
}

The ExportJob object

Attributes

  • idstring
    Crockford-base32 ULID (26 chars).
  • formatenum
    • manifest
    • zip
  • statusenum
    • processing
    • completed
    • failed
  • urlstring (URL), nullable
    Signed URL to the artifact once completed (the JSONL manifest or the ZIP). Re-signed on every read; do not cache the URL, cache the file.
  • url_expires_attimestamp, nullable
    RFC 3339 / ISO 8601 timestamp.
  • total_assetsinteger
    Assets in the selection at creation time.
  • errorobject, nullable
    Show child attributesHide child attributes
    • codestring
    • messagestring
  • created_attimestamp
    RFC 3339 / ISO 8601 timestamp.
  • finished_attimestamp, nullable
    RFC 3339 / ISO 8601 timestamp.

The ExportJob object

{
  "id": "01HX5K2MZ7A3Q4FBNDC0EVDXEX",
  "format": "manifest",
  "status": "processing",
  "url": "https://example.com/…",
  "url_expires_at": "2026-04-27T14:32:00Z",
  "total_assets": 1,
  "error": {
    "code": "string",
    "message": "string"
  },
  "created_at": "2026-04-27T14:32:00Z",
  "finished_at": "2026-04-27T14:32:00Z"
}

Create an export job

POST/v1/exports

Same rows as GET /v1/exports, as a stable artifact: a JSONL manifest (one ExportRow per line) or a ZIP of the image files rendered by the same export pipeline the dashboard uses, with your organization's naming template and per-workflow formats.

Select up to 500 products with product_ids, or omit it for the whole catalogue visible to the API (same cap). Narrow with role.

  • format: manifest is written immediately: the response is already completed with a signed url.
  • format: zip is rendered asynchronously: poll GET /v1/exports/{id} (it carries Retry-After) or subscribe to export.completed / export.failed.

Asset URLs inside a manifest are valid one hour after it was written; the asset ids are permanent — re-fetch bytes with GET /v1/images/{id}. Send Idempotency-Key to make retries return the same job.

Parameters

  • formatenumoptional
    • manifest
    • zip
  • product_idsarray of stringsoptional
    Freeze these products. Omit for the whole catalogue visible to the API (at most 500 products per job; page through GET /v1/exports for more).
  • rolearray of enumsoptional
    Only assets of these roles.

Returns

Returns a ExportJob object with status 202.

Errors
  • 400

    Invalid selection

  • 404

    One or more product_ids not found

  • 500

    Server error

  • 502

    Export pipeline unavailable

POST/v1/exports

curl https://api.veeton.com/v1/exports \
  -H "Authorization: Bearer $VEETON_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "format": "manifest",
  "product_ids": [
    "01HX5K2MZ7A3Q4FBNDC0EVDXY1"
  ],
  "role": [
    "source"
  ]
}'

Response · 202

{
  "id": "01HX5K2MZ7A3Q4FBNDC0EVDXEX",
  "format": "manifest",
  "status": "processing",
  "url": "https://example.com/…",
  "url_expires_at": "2026-04-27T14:32:00Z",
  "total_assets": 1,
  "error": {
    "code": "string",
    "message": "string"
  },
  "created_at": "2026-04-27T14:32:00Z",
  "finished_at": "2026-04-27T14:32:00Z"
}

Export the catalogue

GET/v1/exports

The read a PIM or DAM sync wants: cursor-paginated products, each with every asset we hold for it — your own photos, beautifier renders, tryons and their edits — with a signed URL, the facts needed to file it (role, attributes, suggested_filename) and the facts needed to trust it (ai_generated, watermarked, task_id).

for row in pages:
    product = upsert_by_reference(row.product)
    for asset in row.assets: upsert_asset(product, asset.id, asset.url)

Each asset appears exactly once, under the product it was made for. A tryon of a top styled with pants lives on the top; the pants are listed in also_features, and whether it also goes on the pants page is your merchandising call, not our data model.

asset.id is an image id: a single expired URL is re-fetched with GET /v1/images/{id}, never by re-running the export. URLs are valid for one hour.

Products are those visible to the API (created through it). Assets are the active version of each image — the one the dashboard shows — so a crop or retouch made in the app is what you get. To freeze a selection into a file instead of paging, use POST /v1/exports.

Parameters

  • limitinteger· queryoptional

    Default: 25

  • cursorstring· queryoptional
  • rolestring· queryoptional
    Comma-separated ExportAssetRole values. Products are still listed when none of their assets match; their assets is then empty.
  • sincetimestamp· queryoptional
    Delta mode: only products that changed at or after this instant — a field edited, a photo attached, a generation or edit completed, or the product deleted. Each returned row is the product's full current state, so upsert it whole. Deleted products appear with product.deleted_at set and empty assets. Use the created_at of your previous run (minus a safety margin) as the next since.

Returns

Returns a ExportPage object with status 200.

Errors
  • 400

    Invalid cursor or role

  • 500

    Server error

GET/v1/exports

curl https://api.veeton.com/v1/exports \
  -H "Authorization: Bearer $VEETON_KEY"

Response · 200

{
  "data": [
    {
      "product": {
        "id": "01HX5K2MZ7A3Q4FBNDC0EVDXY1",
        "reference": "TEE-SAGE-001",
        "name": "Crewneck Tee — Sage",
        "sex": "male",
        "deleted_at": "2026-04-27T14:32:00Z"
      },
      "assets": [
        {
          "id": "01HX5K2MZ7A3Q4FBNDC0EVDXY1",
          "role": "source",
          "url": "https://example.com/…",
          "url_expires_at": "2026-04-27T14:32:00Z",
          "mime_type": "image/jpeg",
          "width": 1,
          "height": 1,
          "ai_generated": true,
          "watermarked": true,
          "derived": true,
          "created_at": "2026-04-27T14:32:00Z",
          "task_id": "01HX5K2MZ7A3Q4FBNDC0EVDXY1",
          "attributes": {
            "orientation": "front"
          },
          "also_features": [],
          "suggested_filename": "TEE-SAGE-001_front_cleaned.webp"
        }
      ]
    }
  ],
  "next_cursor": "eyJpZCI6InByb2RfMDFIWCJ9",
  "has_more": true
}

Retrieve an export job

GET/v1/exports/{export_id}

Status and, once completed, a signed URL to the artifact (valid one hour, re-signed on every read). While processing the response carries Retry-After.

Parameters

  • export_idstringrequired
    Crockford-base32 ULID (26 chars).

Returns

Returns a ExportJob object with status 200.

Errors
  • 404

    Not found

GET/v1/exports/{export_id}

curl https://api.veeton.com/v1/exports/01HX5K2MZ7A3Q4FBNDC0EVDXY1 \
  -H "Authorization: Bearer $VEETON_KEY"

Response · 200

{
  "id": "01HX5K2MZ7A3Q4FBNDC0EVDXEX",
  "format": "manifest",
  "status": "processing",
  "url": "https://example.com/…",
  "url_expires_at": "2026-04-27T14:32:00Z",
  "total_assets": 1,
  "error": {
    "code": "string",
    "message": "string"
  },
  "created_at": "2026-04-27T14:32:00Z",
  "finished_at": "2026-04-27T14:32:00Z"
}