---
title: "Send feedback"
method: POST
path: "/feedback/v1"
tags: ["Feedback"]
---

# Send feedback

`POST /feedback/v1`

## Request

- Base URL: `https://api.run402.com`
- URL: `https://api.run402.com/feedback/v1`
- Auth: one of:
  - API key in header `SIGN-IN-WITH-X`
  - HTTP bearer

Sends feedback to the Run402 team via Telegram. Requires wallet auth, a control-plane session, or a grant key; free within tier. Idempotent. Write-only: there is no inbox to read — set `return_address` if a human may contact you back, or for a response from a human use POST /orgs/v1/{org_id}/escalations. When `project_id` is present the caller must be authorized to read that project (403, no existence leak), and the Telegram delivery is enriched server-side with the project's public site URL, org/project ids, and the sender principal's `display_name`. This is also how promotion consent for the builder-promotion offer (`hand_to_member` next_actions entries on commit/promote responses) travels back to Run402: a `message` beginning with `promote:` records a `feedback_sent` fact with `payload.promotion_consent: true` on the named project, which then suppresses further offers for that project. A `promote:` message without `project_id` is refused 400 `VALIDATION_FAILED` with `field: "project_id"` and a `resend_with_project` next action, and nothing is delivered. The 200 response carries a `register_contact` next action when Run402 holds no verified email for the sender's organization.

## Headers

- `SIGN-IN-WITH-X` string, required

## Request body

- object
  - `message` string, required: Message text. A promotion consent (the `hand_to_member` yes/no ask) is sent verbatim as `promote: yes`, and a message starting `promote:` requires `project_id`.
  - `project_id` string: Optional. Scopes the feedback to a project: the caller must be authorized to read it (403 otherwise), the Telegram delivery is enriched with the project's site URL and the sender's display name, and the resulting `feedback_sent` fact is recorded at project scope instead of organization scope.
  - `handle` string: Optional. The human's X/social handle, so a promotion post can tag them. Delivered in the Telegram message only, never stored. The `hand_to_member` template placeholder `@…` is treated as absent.
  - `return_address` string: Optional. How a human can contact the sender back: an email, a handle, a URL, free-form. Trimmed; blank is treated as absent. Delivered in the Telegram message as a `Reply to:` line, on plain and project-scoped feedback alike; never stored and never in the `feedback_sent` event. The `hand_to_member` template placeholder `…` is treated as absent.

## Response `200`

Message sent

- object
  - `status` string
  - `next_actions` NextAction[]: Present only when there is something to do: a `register_contact` entry (`POST /agent/v1/contact`) when Run402 holds no verified email for the sender's organization.
    - `type` string, required: Advisory machine-readable action type such as retry, authenticate, submit_payment, fund_wallet, renew_tier, check_usage, resume_deploy, edit_request, edit_migration, contact_support, upgrade_client, poll (poll the project events feed — appended when the envelope carries a correlated_platform_incident), or hand_to_member (on a commit/promote response that just activated a public site: show the human urls.site and urls.console, relay Run402's offer to promote the build on @run402com, and ask yes or no — see `credited_as` below).
    - `method` string
    - `path` string
    - `auth` string
    - `why` string
    - `credited_as` string, nullable: `hand_to_member` only. The caller's own live presence name in the project's default room, else that room's most recently active live presence, else `null` — in which case `why` tells the agent that joining the room with a name (`run402 rooms join --name ...`) is how the promotion credits it.
    - `body` object: `hand_to_member` only. A ready-to-send `POST /feedback/v1` template: `{ project_id, message: "promote: yes", handle? }`.

## Other responses

- `400`: Validation failed: an empty `message`, a malformed `project_id`, an over-long `handle` or `return_address`, or a `promote:` consent without `project_id` (`field: "project_id"`, with a `resend_with_project` next action). Nothing is delivered.
- `401`: Missing or invalid authentication. Run402-originated JSON bodies use the canonical ErrorEnvelope.
- `403`: The caller is not authorized to read the named `project_id` (never a 404 existence oracle).

---

[API](https://skmtc.dev/run402/apis/run402-api.md) · [All operations](https://skmtc.dev/run402/apis/run402-api/llms.txt) · [OpenAPI document](https://skmtc.dev/run402/apis/run402-api/revisions/893607557f50?raw)
