# Feedback routes

Bug reports and suggestions, read in the admin (ADR 0012)

Bug reports and suggestions, read in the admin (ADR 0012). Generated from `openapi.yaml` of games-api 0.7.0: 1 route.

- [`POST /v1/feedback`](#post-v1-feedback): Send a bug report, a suggestion or another message about the site or a game

Also tagged `feedback`, documented with their first tag:

- [`GET /v1/admin/sites/{siteId}/feedback`](/docs/api/reference/admin/#get-v1-admin-sites-siteid-feedback): Feedback of a site, newest first
- [`GET /v1/admin/feedback/{feedbackId}`](/docs/api/reference/admin/#get-v1-admin-feedback-feedbackid): One feedback message
- [`PATCH /v1/admin/feedback/{feedbackId}`](/docs/api/reference/admin/#patch-v1-admin-feedback-feedbackid): Change the status or the note
- [`DELETE /v1/admin/feedback/{feedbackId}`](/docs/api/reference/admin/#delete-v1-admin-feedback-feedbackid): Delete a feedback message for good

<RouteHeading id="post-v1-feedback" method="POST" path="/v1/feedback" />

<CodePanel title="POST /v1/feedback">
  <Fragment slot="curl">

    ```sh
    curl -X POST 'https://api.filudi.com/v1/feedback' \
      -H "authorization: Bearer $FILUDI_PLAYER_TOKEN" \
      -H 'content-type: application/json' \
      -d '{
      "site": "filudi",
      "game": "gloop",
      "kind": "bug",
      "message": "string",
      "email": "you@example.com",
      "page": "string",
      "locale": "en"
    }'
    ```

  </Fragment>
  <Fragment slot="javascript">

    ```js
    // playerToken: the fp1 token of POST /v1/sdk/players
    const response = await fetch('https://api.filudi.com/v1/feedback', {
      method: 'POST',
      headers: { authorization: `Bearer ${playerToken}`, 'content-type': 'application/json' },
      body: JSON.stringify({
        site: 'filudi',
        game: 'gloop',
        kind: 'bug',
        message: 'string',
        email: 'you@example.com',
        page: 'string',
        locale: 'en',
      }),
    });
    const data = await response.json();
    ```

  </Fragment>
  <Fragment slot="python">

    ```py
    import requests

    # player_token: the fp1 token of POST /v1/sdk/players
    response = requests.post(
        'https://api.filudi.com/v1/feedback',
        headers={'authorization': f'Bearer {player_token}'},
        json={
            'site': 'filudi',
            'game': 'gloop',
            'kind': 'bug',
            'message': 'string',
            'email': 'you@example.com',
            'page': 'string',
            'locale': 'en',
        },
    )
    response.raise_for_status()
    data = response.json()
    ```

  </Fragment>
</CodePanel>

**Send a bug report, a suggestion or another message about the site or a game**

Anyone (ADR 0012). With a player token, the row records the player; a token of another site
than `site` answers 400. An invalid or dead bearer counts as no token, as on sign-in: the route
never answers 401. The API stores the user agent (first 300 characters) and an IP hash,
encrypts `email` at rest, and sends no email. `locale` is kept when it is a locale of the site.
`game` must be in the site catalog; a hidden entry is accepted, since a player may report a game
the site just hid. 5 per IP per hour and 10 per player per day.

Credential, optional: a player token (`fp1`), sent as `Authorization: Bearer <token>`. A game token (`fg1`) answers 401 here. Without a token the answer is the anonymous one.

### Request body

`application/json`, required. The body is a [FeedbackInput](/docs/api/reference/schemas/#schema-feedbackinput).

| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `site` | string | yes | Site slug |
| `game` | string | no | Game slug; absent when the message is about the site |
| `kind` | [FeedbackKind](/docs/api/reference/schemas/#schema-feedbackkind) | yes |  |
| `message` | string | yes | Counted after trim; 10 to 2000 characters |
| `email` | string (email) or string | no | Where the team may reply; "" counts as no email |
| `page` | string | no | Path of the page, without the query string; at most 512 characters; pattern `^/` |
| `locale` | string | no | The page locale; kept when it is a locale of the site |

### Responses

| Status | Body | Description |
| --- | --- | --- |
| 202 | [FeedbackAccepted](/docs/api/reference/schemas/#schema-feedbackaccepted) | Stored for the team. |
| 400 | [Error](/docs/api/reference/schemas/#schema-error) | Validation failed. |
| 404 | none | Unknown site. |
| 429 | [Error](/docs/api/reference/schemas/#schema-error) | Too many requests. Headers: `Retry-After`. |
| 503 | none | Redis is down; the rate limit cannot be checked. |
