API Reference
LegitV API Documentation
Authenticate products programmatically. Send images, get detailed verdicts with confidence scores in seconds.
Base URL: https://api.legitv.ioFormat: JSON
Quick Start
Get your first authentication result in 3 API calls. All requests require a JWT bearer token obtained via Supabase Auth, or a business API key for B2B integrations.
1. Create a verification
POST /api/verify/create
curl -X POST https://api.legitv.io/api/verify/create \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"itemType": "nike_dunk_low",
"listingUrl": "https://vinted.fr/items/123456",
"userDescription": "Nike Dunk Low Panda, size 42"
}'
# Response
{
"id": "ver_abc123",
"status": "draft",
"itemType": "nike_dunk_low",
"createdAt": "2026-03-31T10:00:00Z"
}2. Trigger analysis
POST /api/verify/:id/analyze
curl -X POST https://api.legitv.io/api/verify/ver_abc123/analyze \
-H "Authorization: Bearer <token>"
# Response
{
"status": "queued",
"jobId": "job_xyz789",
"estimatedWait": "~30s"
}3. Get the result
GET /api/verify/:id
curl https://api.legitv.io/api/verify/ver_abc123 \
-H "Authorization: Bearer <token>"
# Response
{
"id": "ver_abc123",
"status": "completed",
"verdict": "authentic",
"confidenceScore": 0.94,
"criteriaResults": [
{
"name": "Label typography",
"score": 0.97,
"status": "pass",
"details": "Font weight and spacing match authentic samples"
},
{
"name": "Stitching pattern",
"score": 0.91,
"status": "pass",
"details": "Stitch density consistent with Nike QC standards"
}
],
"proofHash": "sha256:a1b2c3d4...",
"reportUrl": "/api/verify/ver_abc123/report"
}Authentication
Bearer Token (B2C)
For end-user authentication via Supabase Auth. Include the JWT in every request.
Authorization: Bearer <supabase_jwt_token>
API Key (B2B)
For business integrations. Contact [email protected] to get your key.
X-API-Key: <your_business_api_key>
Endpoints Reference
Verification
POST
Create a draft verificationauth/api/verify/createPOST
Queue AI analysisauth/api/verify/:id/analyzeGET
Get verification resultauth/api/verify/:idGET
List user verificationsauth/api/verify/listDELETE
Delete a verificationauth/api/verify/:idGET
Get queue positionauth/api/verify/:id/queueGET
Download PDF reportauth/api/verify/:id/reportProof & Sharing
GET
Get proof data (public)/api/verify/:id/proofPOST
Verify proof with images (public)/api/verify/proof/checkGET
Get shareable verification/api/shareTemplates
GET
List active product templates/api/templatesGET
Get template with criteria/api/templates/:idGET
Get template by item type/api/templates/by-type/:itemTypeGET
List categories/api/templates/categoriesGET
Zones and photo types/api/templates/criteria-optionsCredits & Billing
GET
Get credit balanceauth/api/credits/balanceGET
List credit packages/api/credits/packagesGET
Transaction historyauth/api/credits/historyPOST
Redeem promo codeauth/api/credits/redeemPOST
Create Stripe checkoutauth/api/credits/checkoutFeedback
GET
Get user feedbackauth/api/feedbackSystem
GET
Health check/healthGET
List AI providers/api/verify/providersGET
Queue statisticsauth/api/verify/queue/statusRequest & Response Format
Create Verification — Request Body
POST /api/verify/create
{
"itemType": "string", // Required — template slug (e.g. "nike_dunk_low")
"listingUrl": "string", // Optional — marketplace listing URL
"images": ["string"], // Optional — array of image URLs or base64
"userDescription": "string" // Optional — item description
}Verification Result — Response
GET /api/verify/:id (completed)
{
"id": "string",
"status": "draft" | "queued" | "processing" | "completed" | "failed",
"verdict": "authentic" | "suspect" | "inconclusive",
"confidenceScore": 0.0 - 1.0,
"criteriaResults": [
{
"criterionId": "string",
"name": "string",
"zone": "label" | "hardware" | "stitching" | "material" | "overall",
"score": 0.0 - 1.0,
"status": "pass" | "fail" | "inconclusive",
"isDealbreaker": false,
"details": "string"
}
],
"proofHash": "sha256:...",
"itemType": "string",
"createdAt": "ISO 8601",
"completedAt": "ISO 8601"
}Webhooks
For async workflows, configure a webhook URL in your business dashboard. We send a POST request when verification completes.
Webhook payload
POST https://your-app.com/webhooks/legitv
Content-Type: application/json
X-LegitV-Signature: sha256=...
{
"event": "verification.completed",
"verificationId": "ver_abc123",
"verdict": "authentic",
"confidenceScore": 0.94,
"completedAt": "2026-03-31T10:00:30Z"
}Rate Limits & SLA
| Plan | Rate Limit | Avg. Response | SLA |
|---|---|---|---|
| Free / B2C | 10 req/min | < 30s | Best effort |
| Starter | 60 req/min | < 20s | 99% |
| Growth | 200 req/min | < 15s | 99.5% |
| Enterprise | Custom | < 10s | 99.9% |
Error Codes
| Code | Meaning | Resolution |
|---|---|---|
| 401 | Unauthorized | Check your token or API key |
| 402 | Insufficient credits | Purchase more credits or upgrade plan |
| 404 | Not found | Check resource ID |
| 422 | Validation error | Check request body format |
| 429 | Rate limited | Reduce request frequency |
SDK Examples
Python
python
import requests
API_URL = "https://api.legitv.io"
API_KEY = "your_api_key"
headers = {"X-API-Key": API_KEY}
# Create verification
resp = requests.post(f"{API_URL}/api/verify/create", headers=headers, json={
"itemType": "chanel_classic_flap",
"listingUrl": "https://vestiairecollective.com/items/..."
})
verification = resp.json()
# Trigger analysis
requests.post(f"{API_URL}/api/verify/{verification['id']}/analyze", headers=headers)
# Poll for result (or use webhook)
import time
while True:
result = requests.get(f"{API_URL}/api/verify/{verification['id']}", headers=headers).json()
if result["status"] == "completed":
print(f"Verdict: {result['verdict']} ({result['confidenceScore']:.0%})")
break
time.sleep(5)Node.js
javascript
const API_URL = "https://api.legitv.io";
const headers = { "X-API-Key": "your_api_key", "Content-Type": "application/json" };
// Create and analyze
const { id } = await fetch(`${API_URL}/api/verify/create`, {
method: "POST",
headers,
body: JSON.stringify({
itemType: "louis_vuitton_neverfull",
listingUrl: "https://vinted.fr/items/789"
})
}).then(r => r.json());
await fetch(`${API_URL}/api/verify/${id}/analyze`, { method: "POST", headers });
// Get result (after webhook or polling)
const result = await fetch(`${API_URL}/api/verify/${id}`, { headers }).then(r => r.json());
console.log(`Verdict: ${result.verdict} (${Math.round(result.confidenceScore * 100)}%)`);Ready to integrate?
Get a free business API key and start your pilot with 100 free verifications.