Skip to main content
Send POST /v1/projects/{project_id}/feedback with an API key that has events:ingest. The key must belong to the same project. A read, write, or errors:write scope alone does not grant capture access.
Example feedback.json:
A successful request returns 201 with id, project_id, and created_at. The response does not repeat the message or contact details. Metadata keys have 1–64 characters. Values can be strings of up to 2,048 characters, finite numbers, booleans, or null. Nested objects and arrays are not accepted. The full request body must be at most 32 KiB. Unknown top-level fields are rejected. Feedback stores telemetry IDs as links. It does not copy trace or replay data. Session, replay, and trace IDs can refer to telemetry that arrives later. An error group must already exist in the same project. Feedback is removed when its project is deleted. Invalid fields return 400; missing credentials return 401; missing scope or project access returns 403; an oversized body returns 413. The CLI accepts the same JSON file:
The typed client provides client.feedback.create(params) with the same fields and response. Capture permits 20 new records per rolling minute and 1,000 per rolling day per project. Excess requests return 429 with Retry-After set to the number of seconds until capacity returns. All keys for a project share these limits. Send an Idempotency-Key header with 1–128 printable ASCII characters to retry safely. The same key and payload return the original 201 response without using quota. A different payload with the same key returns 409. Keys are scoped to the project and remain reserved while the feedback record exists. The TypeScript client creates a stable key for automatic retries; pass { idempotencyKey: "your-key" } as the second argument to feedback.create to reuse a key across calls.

Read and manage feedback

GET /v1/projects/{project_id}/feedback requires errors:read and returns { "data": [...], "next_cursor": null }. Results are ordered newest first. Use limit (1–100, default 50) and pass next_cursor as cursor for the next page. Keep the same filters when you request the next page. Filter by status (new, reviewed, archived), environment, release, service, or error_group_id with exact values. url matches a case-insensitive literal substring of the submitted URL. contact matches a case-insensitive literal substring of the name, email, or user ID. Contact fields are visible only to project readers. GET /v1/projects/{project_id}/feedback/{feedback_id} returns one record. PATCH on the same path accepts a status value of new, reviewed, or archived and requires errors:write. The response contains the updated record. Records include the captured fields, status, and creation/update timestamps. A missing record or a record in another project returns 404.
A replay ID and a session ID are different identifiers. The detail response includes replay_session_id, resolved from the submitted replay_id in the same project. It is null when the ID is invalid or the replay is missing, deleted, or belongs to another project. Use this resolved session ID to open the replay. List and update responses do not resolve replay links. Reuse the same idempotency key and payload when retrying a submission after an uncertain response. Use a new key for each new submission.

Browser requests

The capture endpoint accepts cross-origin POST requests with API-key authentication. OPTIONS preflight does not require a key. Browser clients can send JSON, SDK headers, and Idempotency-Key, and read Retry-After on quota errors. Cookie credentials are not supported.