---
title: "Submits a detection feedback report"
method: POST
path: "/1.1/feedback"
tags: ["Feedback"]
---

# Submits a detection feedback report

`POST /1.1/feedback`

## Request

- Base URL: `https://customer-api.datadome.co`
- URL: `https://customer-api.datadome.co/1.1/feedback`
- Auth: API key in header `x-api-key`

Reports that DataDome classified some of your traffic wrongly, so our analysts can review it and correct the detection.

Describe the traffic with `scope`, which takes an explicit list of identifiers, a traffic filter query, or both, and bound it with `timeWindow`. The window is the closed interval `[start, end]`, so `end` may equal `start` to report a single request.

**Idempotency.** Send an optional `X-Idempotency-Key` header holding a UUID to make a retry safe. Within 24 hours, a repeat of the same key returns the original report with `201` and stores nothing new. Be aware that a repeat with a *different* body also returns the original report, unchanged and without an error, so a key must not be reused for a different submission.

**Rate limit.** 60 requests per minute per API key, shared with the other three Feedback operations.

## Headers

- `X-Idempotency-Key` string, uuid

## Request body

- FeedbackSubmission: A report that some traffic was classified wrongly.
  - `feedbackType` 'falsePositive' | 'falseNegative', required: What the detection got wrong. `falsePositive` reports legitimate traffic that was challenged or blocked. `falseNegative` reports unwanted traffic that was allowed through.
  - `scope` FeedbackScope, required: Which traffic the report covers. Give `entities`, or `trafficFilter`, or both. A request that supplies neither is rejected. A `trafficFilter` that is empty or contains only whitespace counts as not supplied.
    - `entities` object, nullable: An explicit list of identifiers to report. Both members are required when `entities` is present, and `values` must be a JSON array, not an object. `null` in a response when the report was scoped by traffic filter alone.
      - `type` 'ip' | 'requestId' | 'sessionId' | 'userId', required: What kind of identifier `values` holds. Every entry in `values` must be of this kind.
      - `values` string[], required: The identifiers to report. At most 1000 entries, each at most 512 characters. When `type` is `ip`, every entry must be a valid IP address.
    - `trafficFilter` string, nullable: A DataDome query that selects the traffic to report, in the same syntax the dashboard search accepts, for example `countrycode:FR` or `NOT countrycode:(BE OR BG)`. Wildcards are accepted, as in the dashboard search. The query is validated when you submit it; an invalid one is rejected with `400` and the message `Your query is invalid. Please check your query.` `null` in a response when the report was scoped by entities alone.
  - `timeWindow` FeedbackTimeWindow, required: When the traffic you are reporting happened. The window is the closed interval `[start, end]`: both bounds are included, so `end` may equal `start` to report a single instant. The window may span at most 30 days, may not start more than 30 days in the past, and may not extend into the future beyond a 5 minute tolerance for clock skew. Note the deliberate asymmetry with search. A submitted window is closed, while `timeWindowFrom` and `timeWindowTo` on the search operation form the half-open interval `[timeWindowFrom, timeWindowTo)`. Search returns a report when its stored `start` is before `timeWindowTo` and its stored `end` is at or after `timeWindowFrom`, which is correct precisely because the stored window is closed.
    - `start` string, date-time, required: Start of the window, included. ISO-8601 with a timezone offset, to second or millisecond precision. Four or more fractional digits are rejected.
    - `end` string, date-time, required: End of the window, included. Must be at or after `start`; equal bounds denote a single instant.
  - `severity` 'low' | 'medium' | 'high' | 'critical': How much the mistake cost you. Defaults to `medium` when omitted. It orders our review queue and does not change how the report is processed.
  - `origin` 'manualReview' | 'chargebacks' | 'automatedRule' | 'dashboard' | 'datadome' | 'other': Where in your own workflow the report came from. Free to choose from the list; it is stored and returned untouched so you can correlate reports with your internal process.
  - `originId` string: Your own identifier for the case that triggered this report, for example a ticket or chargeback reference. Stored and returned untouched.
  - `feedbackReason` string: A short explanation, in your own words, of why the decision was wrong.

## Response `201`

The report was stored and is awaiting review. Also returned when an `X-Idempotency-Key` is replayed, in which case the body is the original report and nothing new was stored.

- Feedback: A stored report. Every field is always present; a field with nothing to say is `null` rather than absent.
  - `feedbackId` string, uuid: Identifier of the report. Use it to retrieve or cancel the report.
  - `customerId` integer: The account the report belongs to, taken from the API key you submitted it with.
  - `status` 'pending' | 'processing' | 'completed' | 'canceled': Where the report is in our review. A new report is always `pending`. Only a `pending` report can be canceled.
  - `feedbackType` 'falsePositive' | 'falseNegative': What the detection got wrong. `falsePositive` reports legitimate traffic that was challenged or blocked. `falseNegative` reports unwanted traffic that was allowed through.
  - `severity` 'low' | 'medium' | 'high' | 'critical': The severity you submitted, or `medium` when you omitted it.
  - `origin` string, nullable: The origin you submitted, or `null`.
  - `originId` string, nullable: The identifier you submitted, or `null`.
  - `createdAt` string, date-time: When we received the report. ISO-8601 with millisecond precision.
  - `completedAt` string, date-time, nullable: When our review finished. `null` until the status is `completed`, and `null` for a canceled report.
  - `comment` string, nullable: What our analysts concluded. `null` until the review is complete. You cannot set this field.
  - `feedbackReason` string, nullable: The explanation you submitted, or `null`.
  - `expectedDecision` string, nullable: Reserved for a future use. Always `null`, and a request that sets it is rejected. Present only so that clients deserializing the full response do not meet an undeclared field.
  - `timeWindow` FeedbackTimeWindow: When the traffic you are reporting happened. The window is the closed interval `[start, end]`: both bounds are included, so `end` may equal `start` to report a single instant. The window may span at most 30 days, may not start more than 30 days in the past, and may not extend into the future beyond a 5 minute tolerance for clock skew. Note the deliberate asymmetry with search. A submitted window is closed, while `timeWindowFrom` and `timeWindowTo` on the search operation form the half-open interval `[timeWindowFrom, timeWindowTo)`. Search returns a report when its stored `start` is before `timeWindowTo` and its stored `end` is at or after `timeWindowFrom`, which is correct precisely because the stored window is closed.
    - `start` string, date-time, required: Start of the window, included. ISO-8601 with a timezone offset, to second or millisecond precision. Four or more fractional digits are rejected.
    - `end` string, date-time, required: End of the window, included. Must be at or after `start`; equal bounds denote a single instant.
  - `scope` FeedbackScope: Which traffic the report covers. Give `entities`, or `trafficFilter`, or both. A request that supplies neither is rejected. A `trafficFilter` that is empty or contains only whitespace counts as not supplied.
    - `entities` object, nullable: An explicit list of identifiers to report. Both members are required when `entities` is present, and `values` must be a JSON array, not an object. `null` in a response when the report was scoped by traffic filter alone.
      - `type` 'ip' | 'requestId' | 'sessionId' | 'userId', required: What kind of identifier `values` holds. Every entry in `values` must be of this kind.
      - `values` string[], required: The identifiers to report. At most 1000 entries, each at most 512 characters. When `type` is `ip`, every entry must be a valid IP address.
    - `trafficFilter` string, nullable: A DataDome query that selects the traffic to report, in the same syntax the dashboard search accepts, for example `countrycode:FR` or `NOT countrycode:(BE OR BG)`. Wildcards are accepted, as in the dashboard search. The query is validated when you submit it; an invalid one is rejected with `400` and the message `Your query is invalid. Please check your query.` `null` in a response when the report was scoped by entities alone.

## Other responses

- `400`: The body failed validation, or the JSON could not be parsed. Every problem found is listed in `violations`. A malformed JSON document answers `400` too, but with `status` and `message` instead of `violations`.
- `401`: No API key was supplied, or the key is unknown, disabled, or belongs to a blocked account. This response carries no rate-limit headers.
- `403`: Either your plan does not include the Feedback API, or you used a read-only API key on a write. The Feedback API requires Bot Protect on an Enterprise, Enterprise+ or Premium subscription. The plan refusal carries rate-limit headers and consumes one request from your budget; the read-only refusal carries neither.
- `415`: The request did not carry `Content-Type: application/json`.
- `424`: The traffic filter could not be validated because the service that checks it was unreachable. Nothing was stored. Retry in a few minutes.
- `429`: You have used your 60 requests for the current minute. The budget is shared by all four Feedback operations and is counted per API key, so a second key on the same account has its own budget.
- `503`: The report could not be written, or a replayed idempotency key pointed at a report that cannot be read back yet. Retry after the number of seconds in `Retry-After`.

---

[API](https://skmtc.dev/datadome/apis/management-api.md) - [All operations](https://skmtc.dev/datadome/apis/management-api/llms.txt) - [OpenAPI document](https://skmtc.dev/datadome/apis/management-api/revisions/80062169b99e?raw)
