API Reference
Full REST API documentation for the Evodira merchant trust platform.
Base URL
# All requests
https://api.evodira.com/api/v1/{endpoint}
# Example
POST https://api.evodira.com/api/v1/auth/loginThe prefix /api/v1 is required on every request. All responses are JSON. Timestamps are ISO-8601 UTC. IDs are UUIDs.
Authentication
Operator sessions (cookie-based): Call POST /auth/login with email and password. The server sets two HTTP-only cookies:
lmt_access— short-lived JWT used for all authenticated requestslmt_refresh— long-lived token; callPOST /auth/refreshto rotate
Platform API (key-based): Include your API key as an HTTP header on every request:
X-API-Key: <your-platform-api-key>
Platform API keys are managed by a platform_admin in the operator console under Settings → API Keys. Keys are scoped to the platform_api role and cannot call operator-only endpoints (e.g. review decisions, user management).
Inspector sessions: Field inspectors authenticate through the partner app with a separate phone + API key flow. Inspector sessions use lmt_insp_access andlmt_insp_refresh cookies and cannot access internal operator endpoints.
Roles & Permissions
Every protected endpoint requires a specific permission string. A user's effective permissions are determined by their role. Admins can also grant individual permission overrides via PUT /auth/users/{user_id}.
| Role | Who uses it | Permissions included |
|---|---|---|
| platform_admin | Full access to all features and settings. | All permissions |
| qc_lead | QC leadership — review, appeals, corrective actions, tasks, evidence, risk, intelligence, verification. | merchant.read/update/suspend, review.*, appeal.*, corrective_action.*, evidence.*, complaint.read, risk.read, intelligence.read, verification.*, task.*, audit.read, settings.read |
| qc_reviewer | Standard QC analyst — review and corrective actions without high-impact decisions. | merchant.read/update, review.read/decide, appeal.*, corrective_action.*, evidence.*, complaint.read, risk.read, intelligence.read |
| viewer | Read-only access to merchants, evidence, complaints, and risk scores. | merchant.read, review.read, evidence.read, complaint.read, risk.read, intelligence.read, trigger.read |
| inspector | Field inspector — uses partner app, separate cookie auth. | task.read/create/complete, evidence.upload |
| platform_api | Machine-to-machine — uses X-API-Key header. | merchant.create/read, evidence.upload, complaint.ingest, webhook.manage/read, settings.manage |
Endpoints
Risk Score Components
The internal risk score is composed of 9 independently weighted components. Each is a float from 0–1 (higher = more risk). The aggregate internal_score is a weighted mean.
| Component | What it measures |
|---|---|
| identity_confidence | Confidence that the owner's identity is verifiable and consistent |
| location_confidence | GPS accuracy, claimed vs. observed location match, geofence compliance |
| evidence_integrity | Quality and authenticity of submitted visual evidence assets |
| visible_operational_risk | Observable operational issues found in evidence (hygiene, signage, etc.) |
| complaint_risk | Volume, severity, and recency of consumer complaints |
| fulfilment_reliability | Order fulfilment rate, refund frequency, and cancellation patterns |
| reputation_integrity | External signals: social reviews, news mentions, reputation artifacts |
| external_signal_risk | Third-party data signals (regulatory, financial, partner flags) |
| behavioural_anomaly_risk | Unusual patterns in operational behaviour or submission cadence |
Pagination
List endpoints accept skip and limit query parameters. Responses wrap items in a standard envelope:
{
"items": [...],
"total": 142,
"skip": 0,
"limit": 25
}Error Codes
| Status | Meaning |
|---|---|
| 400 | Bad Request — malformed JSON or invalid query parameter |
| 401 | Unauthorized — missing or expired lmt_access cookie, or invalid X-API-Key |
| 403 | Forbidden — authenticated but your role/permissions don't include the required permission |
| 404 | Not Found — resource UUID does not exist or belongs to a different tenant |
| 409 | Conflict — state machine violation (e.g. completing an already-completed action) or duplicate external ID |
| 422 | Validation Error — request body failed field validation (see detail[] array for field paths) |
| 429 | Rate Limit Exceeded — back off and retry after X-RateLimit-Reset |
| 500 | Internal Server Error — check /status for active incidents |
// 422 Validation Error envelope
{
"detail": [
{ "loc": ["body", "email"], "msg": "value is not a valid email address", "type": "value_error" },
{ "loc": ["body", "claimed_address"], "msg": "field required", "type": "missing" }
]
}See Also
Webhooks → — push-based event delivery for risk status changes, review decisions, and trigger firings.
Trust Badges → — embed live merchant trust badges with a single HTML snippet.