Userz

POST /v1/feedback

Submit a feedback report. Returns the persisted feedback id and its initial status.

POST/v1/feedbackAuth: publicKey + optional userToken

Headers

NameTypeDescription
Authorization*Bearer pub_…App public key.
X-Userz-User-TokenJWTPrivate-mode token (see Authentication on the API overview). Required if the App has publicSubmissionEnabled: false.
OriginstringBrowser Origin. Enforced server-side against the App's allowedOrigins list when that list is non-empty.
Content-Type*application/json

Body

NameTypeDescription
text*stringThe report. 1–8192 characters.
severity"low" | "medium" | "high" | nullOptional severity hint.
urlstring (URL, ≤2048 chars)Page the user reported from.
userAgentstring (≤512 chars)Browser UA. Falls back to the request's User-Agent header if omitted.
viewport{ w: number; h: number; dpr: number }Viewport size + device pixel ratio.
consoleLogsConsoleLogEntry[]Up to 500 entries. Each: { level, message (≤1000 chars), ts (epoch ms) }.
attachmentsAttachmentRef[]Up to 10 references to objects you already uploaded via the upload-url endpoint. Each: { key, kind, contentType, byteSize, width?, height? }.
componentTargetComponentTargetOptional targeted component: { name, meta?, bbox?, screenshotKey? }.
metadataRecord<string, unknown>Customer-attached metadata (route, build SHA, feature flags, etc.). Total JSON size ≤4 KB.
identity{ email?, name?, externalUserId? }Self-identifying fields for PUBLIC mode only. Private mode derives identity from the JWT.

Response (201)

JSON
{
  "id": "69e2f2d0ad2f5eef87449d83",
  "status": "received"
}

Status will progress asynchronously through received → sanitizing → sanitized → …. Subscribe to chat-ops for live progress, or poll the feedback record from your dashboard.

Errors

NameTypeDescription
400invalid_bodyZod validation failed; issues array attached.
401missing_authorizationNo Authorization header.
401invalid_authorizationAuthorization header malformed.
401unknown_appNo App matches that public key (or the App was deleted).
401invalid_user_tokenX-Userz-User-Token failed signature/exp/app-id verification.
403origin_not_allowedOrigin header missing or not on the App's allowedOrigins list (when that list is non-empty).
403public_disabledNo X-Userz-User-Token AND publicSubmissionEnabled is false on this App.
429rate_limitedPer-mode rate limit exceeded. Retry after the indicated ms.

Example: public mode

Bash
curl -X POST https://api.userz.ai/v1/feedback \
  -H "Authorization: Bearer pub_GLLHdYCLb2A2d9ieY2LmmwRJ" \
  -H "Content-Type: application/json" \
  -H "Origin: https://app.acme.com" \
  -d '{
    "text": "Mobile login is broken on iOS Safari",
    "severity": "high",
    "url": "https://app.acme.com/login",
    "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X)",
    "viewport": { "w": 390, "h": 844, "dpr": 3 },
    "identity": { "email": "[email protected]" }
  }'

Example: private mode

Bash
curl -X POST https://api.userz.ai/v1/feedback \
  -H "Authorization: Bearer pub_GLLHdYCLb2A2d9ieY2LmmwRJ" \
  -H "X-Userz-User-Token: eyJhbGciOiJIUzI1NiJ9..." \
  -H "Content-Type: application/json" \
  -H "Origin: https://app.acme.com" \
  -d '{ "text": "Wishlist would be great" }'
The end-user identity is derived from the JWT's sub + ctx claims. Any identity field in the body is ignored in private mode.