Skip to main content
Public API V2 is a private preview and is disabled by default. The prompt import contract is implemented, but the production-readiness gate has not passed. Use it only in a preview-enabled workspace and do not treat it as a generally available production dependency yet.
Bulk prompt import is an occasional, one-way write workflow. It appends new prompts to one website and gives you a redacted operation receipt to poll. It is not a prompt-library read, CRUD, replacement, reconciliation, or synchronization API, and an upload never starts an analysis. The V2 prompt surface contains exactly two operations: The generated V2 OpenAPI document is the authoritative machine-readable contract.

Access and authorization

Both operations require a V2-eligible, owner-issued API key with the prompts_write scope. A workspace owner must adopt or rotate an older write key into a V2 integration lineage before it can call these routes. A read key does not gain prompt-library access, and prompts_write does not add a prompt-list operation.
Missing or invalid authentication returns 401. An authenticated key that is not V2-eligible or lacks prompts_write returns 403.

Submit a batch

Each request must be JSON and must stay within both limits:
  • From 1 through 1,000 items.
  • At most 5 MiB for the encoded request body.
Send an exact Content-Type: application/json media type, optionally with parameters such as charset=utf-8. Invalid JSON returns 400 invalid_request, an encoded body over 5 MiB returns 413 payload_too_large, and a different media type returns 415 unsupported_media_type. These failures occur before an operation is created. Only prompt_text is required on an item. It is trimmed and must contain from 5 through 2,000 Unicode characters. Unknown fields are rejected. The generated OpenAPI request requires all four top-level fields: items, defaults, classification, and validate_only. Send empty defaults as {} when you do not need them, and send the selected classification mode and validation flag explicitly.
cURL
client_id is an optional caller-owned correlation value. It must be unique inside the request and match [A-Za-z0-9._-]{1,128}. Receipt items preserve request order and return the zero-based index plus client_id when supplied. They never return prompt text.

Optional fields and defaults

An item can also supply tags, language, search_intent, category, topic, and seed_keyword. defaults can supply only tags, language, and search_intent.

Preserve classification quality

classification.mode controls how missing metadata is handled.

auto mode

auto is the default classification policy and derives only fields that are genuinely missing. Send { "classification": { "mode": "auto" } } explicitly to match the generated OpenAPI contract. The precedence is:
  1. An item value, including an explicit null on a nullable field.
  2. A request default.
  3. A value derived by prompt-classifier-v1.
The classifier never overwrites caller-provided or defaulted values. It derives missing language, search intent, journey tags, category, topic, and seed keyword. Derived search intent uses the three-value enum above. Derived tags use the standard journey taxonomy: Discovery, Comparison, Evaluation, Validation, Objections, Alternatives, and Implementation. Caller-provided custom tags are allowed, but a provided tag array in auto mode must be nonempty and include at least one standard journey tag. Category, topic, and seed keyword remain subject labels rather than aliases for search intent. Every created or would-create item can include field-level classification provenance. Each field reports a source of provided, defaulted, derived, not_applicable, or low_confidence; only derived includes a confidence number. The public classifier version is also returned. Vendor and model names are not part of the public contract. Auto mode fails the whole operation if required language, search intent, or a journey tag cannot be classified confidently. It never silently writes a partially classified fallback. Optional category, topic, or seed keyword can instead be recorded as not_applicable or low_confidence.

provided_only mode

Use provided_only when your integration owns its taxonomy or prompt content must not be sent to the classification provider:
This mode never invokes the classifier. Every item needs an effective language, either on the item or in defaults. An explicit empty tags array is allowed. Other omitted or nullable classification fields may remain empty.
provided_only opts out of automatic classification completeness. To retain the same downstream filtering coverage, supply language, at least one standard journey tag, search intent, category, topic, and seed keyword where they apply. Omitted fields remain absent rather than being inferred, so related classifications and filters can be unavailable. Validate your own taxonomy before uploading.

Validate, then write

Set validate_only: true to run normalization, duplicate detection, classification, and prompt-limit projection without creating prompts. A successful validation receipt uses would_create, active_count, projected_active_count, and prompt_limit. Validation is a separate asynchronous operation. It does not reserve prompt capacity and cannot be promoted into a write, so state may change before the real upload. Use two different idempotency keys:
  1. Submit validate_only: true with a validation key and poll it to a terminal receipt.
  2. If validation succeeds, submit the same items with validate_only: false and a new write key.
  3. Poll the write receipt independently.
Reusing the validation key for the write returns 409 idempotency_conflict because validate_only is part of the request fingerprint.

Idempotency and retry rules

Every POST requires an Idempotency-Key containing from 16 through 255 visible ASCII characters. Generate a random UUID for each new operation and persist it with the exact request body before sending. Follow these retry rules:
  • If the POST response is lost or transport status is uncertain, resend the exact request with the same idempotency key.
  • JSON object-key order does not affect the fingerprint, but array order does. Preserve item and tag order when retrying rather than reconstructing a batch.
  • For a pre-acceptance 429, wait for Retry-After, then retry the exact request with the same key.
  • For a POST 500 or 503, the acceptance result may be uncertain. Retry the exact request with the same key using bounded exponential backoff and jitter; idempotency resolves it to at most one operation.
  • Replaying a terminal receipt never reruns it. If its error says retryable: true and retry_strategy: "new_idempotency_key", start a new operation with a new key.
  • If retryable is false, do not automate a retry. Correct the request or resolve the reported capacity/classification issue first.

Poll the receipt

The POST response includes a relative Location such as:
Every receipt uses the common V2 success envelope. Every representation contains id, object, website_id, status, validate_only, created_at, and expires_at:
GET that location until data.status is succeeded or failed:
cURL
Receipt GET always returns 200 while the receipt exists. A pending or processing receipt includes Retry-After: 2; wait at least that many seconds before polling again. Terminal receipts omit Retry-After. For a polling GET 429, preserve the same URL and wait for Retry-After. For GET 500 or 503, retry the same URL with bounded exponential backoff and jitter. Polling never creates an operation and does not use an idempotency key. Stop when the receipt is terminal or its documented expires_at has passed. Terminal item shapes are closed and safe to decode by status:
A successful validation uses would_create instead of created. A failed receipt uses failed with classification_failed only on classification failures, skipped for already-detected duplicates, and not_processed for other items. Branch on the closed status and code fields rather than a message string. 202 means the operation was durably accepted; it does not mean prompts were created. Prompts commit only when the terminal receipt is succeeded and validate_only is false.

Atomic batches, duplicates, and capacity

Each request is one atomic boundary. A successful write creates every eligible prompt that is not a duplicate. A classification, prompt-limit, or commit failure creates none of the submitted prompts; failed item results are diagnostic and do not mean a partial write occurred. The API does not silently chunk a request. If your upload exceeds 1,000 items or 5 MiB, partition it deliberately. Treat each partition as an independent atomic operation with its own idempotency key, preserve stable client_id values, and record which operations belong to your source upload. Atomicity does not span partitions. Prompt deduplication normalizes Unicode, case, and whitespace while preserving punctuation. The first normalized occurrence in a request wins. Existing duplicates are skipped rather than updated, reactivated, or reclassified: Duplicates are safe skips. The summary’s three duplicate breakdown counts add up to skipped_duplicates. The website’s prompt_limit counts active prompts. A validation reports the current and projected active counts. If a write would exceed the limit, the operation fails with prompt_limit_exceeded, every prompt that is not a duplicate remains not_processed, and created is zero. Remove or deactivate prompts in the management surface, reduce the batch, then validate again with a new key.

Terminal failure strategies

A deterministic classification_failed receipt identifies failed item indexes and safe client_id values but does not echo content. A transient classifier dependency is retried internally before it becomes classification_unavailable. Never split and retry only the failed items from an atomic operation unless you intentionally want a different upload.

Receipt retention, redaction, and key rotation

Receipts and their idempotency state expire together 30 days after acceptance. After expires_at, GET returns tenant-safe 404 not_found and the old idempotency key may be reused. Normalized prompt deduplication still protects existing prompts. Receipts contain counts, item indexes, optional client_id, closed status/error codes, timestamps, and field-level classification provenance. They do not contain prompt text, prompt IDs, tags, languages, intent/category/topic values, seed keywords, or arbitrary provider details. Submitted content is held only in encrypted short-lived staging, removed after terminal processing, and subject to a 24-hour hard TTL. Receipt lookup is bound to the workspace, website, and integration lineage. If an owner rotates a key while preserving its lineage, the successor key can replay the original POST or GET the original receipt during the 30-day window. An independently issued integration cannot read that receipt and receives the same 404 as a missing resource. A workspace owner can recover a receipt through the authenticated management surface. For an operational rotation, a workspace owner opens Settings → Public API Keys, selects Rotate key on the existing integration, and replaces the secret in the client’s secret store. Rotation keeps that integration’s lineage; creating an unrelated key does not. If the client no longer has a lineage key, the owner can use Recover a prompt import receipt on the same settings page with the web_… and pim_… IDs.

Migrate the V1 prompt upload

Public API V1 is protocol-deprecated, but its prompt-import route is still operational today. It does not return 410 yet. It will retire without a redirect only after the V2 production-readiness gate passes and the public documentation is updated. Do not migrate by changing only v1 to v2:

Upgrade checklist

  • Request V2 private-preview access for the target workspace.
  • Have a workspace owner issue or adopt a V2-eligible prompts_write key and record its integration lineage in your key-rotation procedure.
  • Move website scope from the body to the path and remove mode, partial, and caller-controlled source.
  • Add stable client_id values so redacted receipt items can be reconciled to your source file without prompt text.
  • Choose auto or provided_only explicitly and verify taxonomy and provenance handling.
  • Enforce the 1,000-item and 5 MiB limits client-side. Make any larger partitioning explicit; never assume server-side chunking.
  • Persist request body, item order, idempotency key, import ID, and receipt expiry as one client operation record.
  • Implement separate validation and write idempotency keys, Location handling, Retry-After polling, terminal status handling, and the retry matrix above.
  • Treat a successful validation as a projection, not a reservation. Check the terminal receipt for the write before considering the upload complete.
  • Test key rotation and same-lineage receipt recovery before cutover.
  • Keep the V1 and V2 adapters separate. There is no redirect, dual write, or automatic fallback between versions.
  • Keep production use disabled until Videntic announces that the prompt-import production-readiness gate has passed.

Private-preview status

This endpoint has not passed its production-readiness gate and has no general availability or production SLA commitment. Videntic is still validating its availability, operational monitoring, regression detection, and support process before a broader release. Preview access and support expectations are agreed directly with each participating workspace. Until Videntic announces that the gate has passed, keep production use disabled, maintain your own client-side operation log, and alert on terminal failures or operations approaching the 30-minute processing deadline. To request access or report a preview issue, contact [email protected] with request IDs, import IDs, timestamps, and affected routes. Never include API keys or prompt text.

Migrate from V1 to V2

Review the broader version boundary, read migration, and rollback plan.

V2 OpenAPI

Inspect the generated request and receipt schemas.
Last modified on July 17, 2026