Feedback API
The Feedback API allows you to provide feedback on decisions and events to improve fraud detection accuracy.
Auth
x-api-key is required.
Endpoints
POST /api/v1/feedback/decision/:idPOST /api/v1/feedback/event/:id
Label Decision
Provide feedback on a decision outcome.
Endpoint
POST
/api/v1/feedback/decision/:idPOST /api/v1/feedback/decision/:id
Headers
| Header | Description |
|---|---|
| Idempotency-Key | Optional. Unique key to prevent duplicate submissions |
Request
{
"label": "FRAUD",
"notes": "Customer confirmed this was fraudulent activity",
"externalCaseId": "case_12345"
}Response
{
"id": "feedback_abc123",
"type": "DECISION",
"targetId": "evt_ckm9876543210",
"label": "FRAUD",
"notes": "Customer confirmed this was fraudulent activity",
"externalCaseId": "case_12345",
"createdAt": "2025-01-15T10:00:00Z",
"updatedAt": "2025-01-15T10:00:00Z"
}Label Event
Provide feedback on an event outcome.
Endpoint
POST
/api/v1/feedback/event/:idPOST /api/v1/feedback/event/:id
Request
Same format as decision feedback.
Feedback Labels
| Label | Description |
|---|---|
| FRAUD | Confirmed fraudulent activity |
| LEGIT | Confirmed legitimate activity |
| CHARGEBACK | Chargeback occurred |
| REFUND | Refund was issued |
| FALSE_POSITIVE | Decision was incorrect (blocked legitimate transaction) |
| TRUE_POSITIVE | Decision was correct (blocked fraudulent transaction) |
Idempotency
Feedback endpoints support idempotency to prevent duplicate submissions. Include Idempotency-Key:
POST /api/v1/feedback/decision/evt_123
Idempotency-Key: unique-key-here
Content-Type: application/json
{
"label": "FRAUD",
"notes": "Customer confirmed fraud"
}Expected behavior
- First request: processed normally and the response is stored for replay
- Duplicate key (same tenant + same endpoint path): returns the stored response body
- Keys expire after 24 hours
- Reuse the same key for safe retries of the same logical action
Example with Idempotency
const idempotencyKey = `feedback-${decisionId}-${Date.now()}`;
const response = await fetch(
`https://api.naiza.ai/api/v1/feedback/decision/${decisionId}`,
{
method: 'POST',
headers: {
'x-api-key': 'naiza_api_sk_live_...',
'Idempotency-Key': idempotencyKey,
'Content-Type': 'application/json',
},
body: JSON.stringify({
label: 'FRAUD',
notes: 'Customer confirmed fraud',
}),
}
);
// Safe to retry with same idempotency key
// Will return cached response if already processedExamples
# Label decision as fraud
curl -X POST https://api.naiza.ai/api/v1/feedback/decision/evt_123 \
-H "x-api-key: naiza_api_sk_live_..." \
-H "Idempotency-Key: feedback-evt_123-1234567890" \
-H "Content-Type: application/json" \
-d '{
"label": "FRAUD",
"notes": "Customer confirmed this was fraudulent",
"externalCaseId": "case_12345"
}'Best Practices
1. Use Idempotency Keys
Always use idempotency keys when submitting feedback to prevent duplicates:
const idempotencyKey = `${decisionId}-${label}-${timestamp}`;2. Include External Case IDs
Link feedback to your internal case management system:
{
"label": "FRAUD",
"externalCaseId": "case_12345",
"notes": "Linked to support ticket #12345"
}3. Provide Detailed Notes
Include context in notes for better model training:
{
"label": "FALSE_POSITIVE",
"notes": "Customer verified identity via phone call. Original decision was incorrect."
}4. Handle Retries
Implement retry logic with the same idempotency key:
async function submitFeedbackWithRetry(decisionId, label, notes, maxRetries = 3) {
const idempotencyKey = `feedback-${decisionId}-${label}`;
for (let i = 0; i < maxRetries; i++) {
try {
return await submitFeedback(decisionId, label, notes, idempotencyKey);
} catch (error) {
if (i === maxRetries - 1) throw error;
await sleep(Math.pow(2, i) * 1000); // Exponential backoff
}
}
}Troubleshooting
404: target decision/event ID not found in your tenant scope401: missing/invalid API key422/400: body validation failed (invalidlabel, oversizednotes, etc.)