URL: /guides/feedback-api

---
title: "Feedback API"
description: "Send feedback on FormShield classifications — from the dashboard or programmatically — to calibrate the models."
---

FormShield learns from corrections. When a verdict is wrong — a real customer flagged as a datacenter bot, a legit domain scored as disposable — you tell us, and that correction becomes training signal. Feedback flows into a per-model label corpus that recalibrates the scoring weights.

There are two ways to send it: the **dashboard** (click), and the **API** (for agents and integrations).

## From the dashboard

Open a project → **Live log** → click any row. The detail panel has:

- **Was this verdict right?** — 👍 Correct / 👎 Wrong, with an optional note.
- On an IP row, **"Not a datacenter / VPN / proxy / scanner"** chips to fix a specific reputation flag.

Each click is recorded against your org and feeds the corpus immediately.

## From the API

`POST /v1/feedback` lets an agent that called `/v1/check`, `/v1/ip`, or `/v1/email` send a correction back. Authenticate with your API key — the org is derived from the key. Feedback calls are **free** (no credits).

### Request

```bash
curl -X POST https://api.formshield.dev/v1/feedback \
  -H "Authorization: Bearer fs_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "ipatlas-reputation",
    "entity_type": "ip",
    "entity_id": "203.0.113.42",
    "kind": "verdict",
    "new_label": "bad",
    "note": "scored high-risk but this is our office VPN"
  }'
```

| Field | Required | Description |
| --- | --- | --- |
| `model` | yes | `ipatlas-reputation`, `email`, `fusion`, `content`, or `voight` |
| `entity_type` | yes | `ip`, `email`, `content`, or `request` |
| `entity_id` | yes | The IP address, email, or event id the verdict was about |
| `kind` | no | `verdict` (default) — rate the classification; or `feature_correction` |
| `new_label` | yes | For `verdict`: `good` (right) or `bad` (wrong). For `feature_correction`: the corrected value |
| `target_feature` | when `kind=feature_correction` | The feature to correct, e.g. `datacenter` |
| `note` | no | Free-text context (≤ 1000 chars) |

### Response

```json
{
  "version": "1",
  "data": {
    "id": "mfb_VLvMQENMQrl",
    "model": "ipatlas-reputation",
    "entity_type": "ip",
    "entity_id": "203.0.113.42",
    "kind": "verdict",
    "new_label": "bad",
    "scope": "org",
    "status": "active",
    "confidence": 0.8,
    "source_tier": "api",
    "created_at": "2026-06-08T03:14:00.000Z"
  }
}
```

### Correct a specific feature

When the verdict was right overall but one signal is wrong — say an IP is correctly low-risk but mislabeled a datacenter — send a feature correction instead:

```bash
curl -X POST https://api.formshield.dev/v1/feedback \
  -H "Authorization: Bearer fs_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "ipatlas-reputation",
    "entity_type": "ip",
    "entity_id": "203.0.113.42",
    "kind": "feature_correction",
    "target_feature": "datacenter",
    "new_label": "false",
    "note": "this is a residential ISP range, not a datacenter"
  }'
```

A feature correction does two things: it's a high-confidence training label, **and** it seeds a first-party override so the misclassification is fixed for your org while the model relearns.

## What happens to it

Each correction is scoped to your org and stored with a snapshot of the features the model saw, so the trainer can learn from exactly what produced the verdict. Your feedback only affects your org's results until it's verified and graduated to platform-wide ground truth.

<Note>
Feedback is org-scoped by default. We never auto-treat un-corrected traffic as "correct" — only an explicit signal labels it.
</Note>
