# Send feedback

> Tell Solvecha whether Google accepted the answer of a reCAPTCHA job. Optional, free of charge.

`POST https://api.solvecha.com/v1/feedback`


After you submit our answer to Google, you can tell us whether Google accepted it. This helps us improve the models. It is optional and costs no quota. The browser extension does this for you.

## Authorization

Send your API key as `Authorization: Bearer YOUR_API_KEY`. Other ways are the `key` field of the body and the `key` query parameter. See [Authentication](https://solvecha.com/docs/authentication.md).

## Request body

JSON, or url-encoded form data. The body is limited to 4.5 MB.

| Name | Type | Required | Description |
|---|---|---|---|
| `key` | string | No | Your API key, if you do not send it in the `Authorization` header or the query string. |
| `job_id` | string | Yes | The job id from the create response. It must be a reCAPTCHA job of your key. |
| `verdict` | string | Yes | Whether Google accepted the answer. One of `accepted`, `rejected`. |
| `grid` | string | Yes | The grid size of the challenge. One of `1x1`, `3x3`, `4x4`. |
| `round_index` | integer | No | The number of the round in the challenge, from 0 to 64. |

Only JSON bodies up to 4 KB are accepted here, not form data. No pictures and no page address are sent.

## Example request


**cURL**

```bash
curl -X POST "https://api.solvecha.com/v1/feedback" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "job_id": "1234567",
  "verdict": "accepted",
  "grid": "3x3",
  "round_index": 0
}'
```

**Python**

```python
import requests

response = requests.post(
    "https://api.solvecha.com/v1/feedback",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    json={
        "job_id": "1234567",
        "verdict": "accepted",
        "grid": "3x3",
        "round_index": 0
    },
)
print(response.status_code, response.json())
```

**Node.js**

```js
const response = await fetch("https://api.solvecha.com/v1/feedback", {
  method: "POST",
  headers: {
    Authorization: "Bearer YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "job_id": "1234567",
    "verdict": "accepted",
    "grid": "3x3",
    "round_index": 0
  }),
});
console.log(response.status, await response.json());
```

**Go**

```go
package main

import (
	"fmt"
	"io"
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{
  "job_id": "1234567",
  "verdict": "accepted",
  "grid": "3x3",
  "round_index": 0
}`)
	req, err := http.NewRequest("POST", "https://api.solvecha.com/v1/feedback", body)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
	req.Header.Set("Content-Type", "application/json")
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	out, _ := io.ReadAll(resp.Body)
	fmt.Println(resp.StatusCode, string(out))
}
```


## Response

### 200 OK

The verdict is stored. The first verdict per job counts. A repeat changes nothing.

```json
{"data": "ok"}
```

### Errors

An error has the HTTP status of its code and this body:

```json
{"error": 15, "code": 15, "message": "Invalid key", "type": null}
```

| Code | HTTP status | When |
|---|---|---|
| `10` Invalid request | 400 | The body is not valid JSON, a field is wrong, or the job is unknown, not yours, or not a reCAPTCHA job. |
| `11` Rate limit reached | 429 | Your key is above the create requests per minute of its plan. |
| `15` Invalid key | 401 | The key is missing, malformed or unknown. |
| `9` Unknown error | 500 | Server error. Retry after a few seconds. |

All codes are on the [Errors](https://solvecha.com/docs/errors.md) page.
