Batch-ingest category form-data (wizard step 4)
PUT/api/v1/products/:id/form-data
Required scope: dpp:draft:write. A WRITE (HMAC + Idempotency-Key).
The headless equivalent of filling the wizard's field sections: push a
partial batch of category field_id -> value pairs and get a
fail-closed, FIELD-LEVEL accept/reject. Every provided field is checked
against the category schema (type / enum / range / pattern) and unknown
fields are REJECTED (422 FIELD_VALIDATION_ERROR, details.fieldErrors[]),
never silently dropped — so a mis-mapped ERP column is immediately
visible. Required-completeness is NOT enforced here (a partial batch is
allowed); it is reported by the publish gate. On success the response
echoes the post-write completeness score and a compact readiness
summary. lockVersion gives optimistic concurrency (stale -> 409).
Request
Responses
- 200
- 400
- 401
- 403
- 404
- 409
- 422
- 429
- 503
Ingested (fully validated)
400 — INVALID_JSON, VALIDATION_ERROR, or IDEMPOTENCY_KEY_REQUIRED.
401 — INVALID_SIGNATURE or SIGNING_NOT_CONFIGURED (or bearer auth failure).
403 — missing scope (FORBIDDEN_SCOPE) or module (FORBIDDEN_MODULE).
404 — not found OR owned by another tenant (NOT_FOUND; IDOR-safe).
Optimistic lock conflict (LOCK_CONFLICT) — re-GET and retry.
Field-level validation failure (FIELD_VALIDATION_ERROR).
details.fieldErrors[] carries {field_id, label, code, message} —
field references only, never the submitted values (PII redaction).
429 — RATE_LIMITED (per-key limit, reads and writes alike; fails closed,
so a limiter outage also returns 429). A limiter-down 429 is deliberately
indistinguishable from a quota 429. Carries Retry-After (seconds).
Response Headers
Seconds to wait before retrying (429 only).
Per-minute request ceiling for this key's tier.
Requests left in the current window (floored at 0).
Seconds until the window resets.
503 — the API is not enabled on this environment (FEATURE_DISABLED).