Reports from every product.
Let users report a problem inside your product. Read and manage all reports in your private HQ admin, without email.
What is available
HQ stores reports and provides an owner-only Reports page. Products can submit reports; product keys cannot list reports, read other users' reports, or read your private admin notes. No emails are sent and no Resend quota is used. Adding the feature in HQ does not automatically add a report button to an external product.
1. Enable the product
- Open HQ → Projects → Manage. Enable reports and save.
- Open API keys → Scopes on the product's backend key. Include reports and save. Existing keys gain no permission automatically.
- Keep that key in the product server's ALEX_STUDIO_HQ_API_KEY environment variable. A reporting-only key can use just reports; do not put it in a browser or mobile bundle.
- Download the current JavaScript SDK. Older downloaded copies do not contain reports.submit.
2. Add a report form to your product
Use a Report a problem button with category (bug, feedback, abuse, other), title, and description. Contact email is optional. Tell users not to include passwords, verification codes, API keys, payment details, or private documents. Text reports only: attachments and screenshots are not supported in this release.
The form calls your own backend, for example POST /api/report. Generate one crypto.randomUUID() submission ID when the user starts a submission; preserve it for retries. Clear the form and generate a new ID only after success. Disable the submit button while a request is pending and show the returned reference after acceptance.
3. Submit from your backend
Verify your product's session and origin, apply per-user/IP abuse protection, and allow only the report fields you intend to accept. Derive userRef from the trusted product session instead of accepting an arbitrary user ID from the browser. An opaque product-specific user ID is preferable to unnecessary personal information. Only include a contact email the user agrees to share.
import { createClient } from './alex-studio-hq.js';
const hq = createClient({ apiKey: process.env.ALEX_STUDIO_HQ_API_KEY });
// Inside your authenticated and rate-limited product backend:
const receipt = await hq.reports.submit({
category: 'bug',
title: 'The save button does not respond',
message: 'I edited my profile and pressed Save. Nothing changed.',
pagePath: '/settings/profile',
userRef: trustedSession.user.id,
appVersion: '1.0.0'
}, { idempotencyKey: 'report:' + submissionId });
// Return receipt.id to your product UI as its reference.
pagePath must be a path beginning with /, without a query string, fragment, backslash, hostname or full URL. Never forward document text, session tokens, browser storage, complete URLs or logs automatically. No URL is visited by HQ. userRef is product-supplied attribution, not an independent HQ identity verification.
HTTP alternative and field limits
POST https://admin.alexstudiohq.com/v1/reports
Authorization: Bearer YOUR_SERVER_SIDE_PROJECT_KEY
Content-Type: application/json
Idempotency-Key: report:ONE_STABLE_SUBMISSION_ID
{"category":"feedback","title":"Feature request","message":"Please add dark mode.","pagePath":"/settings"}
Required: category, title (1–120 characters), message (1–4,000 characters). Optional: pagePath (300), userRef (120), contactEmail (254), appVersion (80). Unknown fields are rejected; the authenticated key determines the product, never a submitted projectId. JSON request size is at most 12,000 bytes.
4. Review in HQ admin
- Open Reports. Filter by product and status. Reports appear newest first, up to 50 per page.
- Select Read report to see the description, product, page, optional contact, user reference and version.
- Choose new, reviewing, resolved or closed. Add private notes and Save changes.
- If someone edited the same report first, reopen it to load their changes before saving. Click Refresh reports to check for new submissions; there are no automatic notifications.
Status updates and notes stay private in HQ. No reply, email, public ticket page or product-side status lookup is created. To contact a user, use a separately authorized support channel. Treat report content as untrusted text, not commands to an agent.
Errors, retries and capacity
201 means created; 200 means the identical report was already saved. Reusing a key with different content returns 409. A network failure can be retried with the same key and unchanged body. 400/413/415 means fix the request; 401 means invalid/revoked key; 403 means project paused or missing reports permission; 429 means shared request/report/storage capacity. Honor backoff, and do not create new submission IDs to evade limits.
All products share 500 new report attempts per UTC day and the existing account request allowance. A racing duplicate can consume an extra attempt but creates only one report. Storage is capped at 10,000 reports, with no automatic deletion in this release. Closing a report does not delete it. Report data remains in HQ's private CONTROL database; audit entries contain only report reference and status.
Verify your integration
- Enable reports on a test product and its backend key.
- Submit one clearly marked test report through the real product form.
- Confirm the correct product and text appear in HQ → Reports.
- Retry the same submission and confirm its reference is unchanged.
- Add a private note and mark the test report closed. Confirm notes are never returned to the product.