{"openapi":"3.0.3","info":{"title":"Boltt Device Services Platform — UAT API","version":"1.0.0","description":"REST API for the **Boltt Device Services Platform (DSP)** — device activation, customer OTP registration, warranty, OTA firmware delivery, telemetry, crash reporting and device lifecycle management.\n\nImplements **Technical Specification v1.0** (Bitmisri / DSP Team, June 2026). **TEST ENVIRONMENT ONLY** — all data is seeded and simulated; no real SMS or S3 traffic.\n\n### Authentication\n| Token | Obtained from | Header |\n|---|---|---|\n| SDK API Key | credentials report (`/report`) | `X-SDK-API-Key: <key>` |\n| `device_token` (JWT, 90 d) | `POST /device/activate` | `Authorization: Bearer <token>` |\n| `user_token` (JWT, 30 d) | `POST /user/verify-otp` | `Authorization: Bearer <token>` |\n| `admin_token` (JWT, 8 h) | `POST /auth/admin/login` | `Authorization: Bearer <token>` |\n\nAll errors use the standard envelope with a `DSP-xxx` error code, human-readable `message`, field-level `details[]` where applicable, and a `trace_id` for support. Ready-to-use seeded credentials live in the [credentials report](/report).","contact":{"name":"Bitmisri / DSP Team"}},"servers":[{"url":"https://boltt-backend.rad0.dev/dsp/v1","description":"UAT (this host)"}],"tags":[{"name":"Activation","description":"Device onboarding — SDK API key auth"},{"name":"Customer & OTP","description":"Customer registration and device-user linking"},{"name":"Warranty","description":"Warranty registration and business rules"},{"name":"OTA","description":"Firmware update check and rollout reporting"},{"name":"Telemetry & Health","description":"Heartbeat, telemetry batches, crash reports"},{"name":"Device Lifecycle","description":"Configuration, profile, unregistration"},{"name":"Admin","description":"UAT admin token issuance"},{"name":"Platform","description":"Health and metadata"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"device_token, user_token or admin_token depending on endpoint"},"sdkApiKey":{"type":"apiKey","in":"header","name":"X-SDK-API-Key","description":"SDK API key — used only by POST /device/activate"}},"schemas":{"ErrorResponse":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error_code":{"type":"string","example":"DSP-001"},"error":{"type":"string","example":"IMEI_ALREADY_REGISTERED"},"message":{"type":"string"},"details":{"type":"array","description":"Field-level validation explanations (when applicable)","items":{"type":"object","properties":{"field":{"type":"string"},"issue":{"type":"string"},"hint":{"type":"string"}}}},"trace_id":{"type":"string","example":"trace-20260612-abc12345"},"timestamp":{"type":"string","format":"date-time"}}},"Configuration":{"type":"object","properties":{"heartbeat_interval_seconds":{"type":"integer","example":21600},"telemetry_enabled":{"type":"boolean","example":true},"crash_report_enabled":{"type":"boolean","example":true},"ota_check_interval_hours":{"type":"integer","example":24},"max_log_level":{"type":"string","example":"warn"},"feature_flags":{"type":"object","additionalProperties":true}}}}},"paths":{"/device/activate":{"post":{"tags":["Activation"],"summary":"Activate a device","operationId":"activateDevice","description":"Registers a new Boltt device. Called by the Activation SDK on first boot. Validates IMEI (15-digit Luhn), checks the model allow-list, creates the registry record and returns a 90-day `device_token`.\n\n**Auth:** `X-SDK-API-Key` header — no JWT at activation.\n\n**Rate limit:** 3 attempts per IMEI per 24 h.","security":[{"sdkApiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["imei1","serial_number","model_code","model_name","device_type","android_version","build_id","sdk_version"],"properties":{"imei1":{"type":"string","description":"15-digit numeric, Luhn-valid","example":"356938035643809"},"imei2":{"type":"string","description":"Optional secondary IMEI (dual-SIM); must differ from imei1","example":"490154203237518"},"serial_number":{"type":"string","example":"BOLTT2026XP001234"},"model_code":{"type":"string","example":"BOLTT-PH5G-2026"},"model_name":{"type":"string","example":"Boltt Phantom 5G"},"device_type":{"type":"string","enum":["smartphone","tablet","wearable","iot"]},"android_version":{"type":"string","example":"13.0"},"build_id":{"type":"string","example":"INCAR-BOLTT-PH5G-260601.001"},"sdk_version":{"type":"string","example":"1.2.3"},"country":{"type":"string","example":"IN"}}}}}},"responses":{"201":{"description":"Device activated; returns device_id, device_token and initial configuration","content":{"application/json":{"example":{"success":true,"device_id":"d8f3a1c2-4e56-7890-abcd-ef1234567890","device_token":"eyJhbGciOiJIUzI1NiIs...","token_expiry":"2026-09-10T00:00:00Z","configuration":{"heartbeat_interval_seconds":21600,"telemetry_enabled":true,"crash_report_enabled":true,"ota_check_interval_hours":24},"message":"Device activated successfully"}}}},"401":{"description":"**DSP-004 INVALID_SDK_API_KEY** (HTTP 401) — SDK key missing or revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error_code":"DSP-004","error":"INVALID_SDK_API_KEY","message":"SDK key missing or revoked","trace_id":"trace-20260612-abc12345","timestamp":"2026-06-12T10:30:00Z"}}}},"409":{"description":"**DSP-001 IMEI_ALREADY_REGISTERED** (HTTP 409) — Device already activated; existing device_id is returned in the body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error_code":"DSP-001","error":"IMEI_ALREADY_REGISTERED","message":"Device already activated; existing device_id is returned in the body","trace_id":"trace-20260612-abc12345","timestamp":"2026-06-12T10:30:00Z"}}}},"422":{"description":"**DSP-002 INVALID_IMEI_FORMAT** (HTTP 422) — IMEI fails Luhn/length check, or model not supported (DSP-003), or other field validation (DSP-998)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error_code":"DSP-002","error":"INVALID_IMEI_FORMAT","message":"IMEI fails Luhn/length check, or model not supported (DSP-003), or other field validation (DSP-998)","trace_id":"trace-20260612-abc12345","timestamp":"2026-06-12T10:30:00Z"}}}},"429":{"description":"**DSP-005 RATE_LIMIT_EXCEEDED** (HTTP 429) — More than 3 activation attempts for this IMEI in 24 h","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error_code":"DSP-005","error":"RATE_LIMIT_EXCEEDED","message":"More than 3 activation attempts for this IMEI in 24 h","trace_id":"trace-20260612-abc12345","timestamp":"2026-06-12T10:30:00Z"}}}}}}},"/user/request-otp":{"post":{"tags":["Customer & OTP"],"summary":"Request OTP","operationId":"requestOtp","description":"Generates a 6-digit OTP for the customer mobile (Indian E.164). SMS delivery is **simulated in UAT** — verify with the UAT bypass code from the credentials report.\n\n**Auth:** `device_token`.\n\n**Rate limit:** 5 OTPs per mobile per hour. OTP TTL: 10 minutes.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["mobile_number","purpose","device_id"],"properties":{"mobile_number":{"type":"string","example":"+919876543210"},"purpose":{"type":"string","enum":["registration","warranty","account_recovery"]},"device_id":{"type":"string","format":"uuid"}}}}}},"responses":{"200":{"description":"OTP generated and (simulated) sent","content":{"application/json":{"example":{"success":true,"request_id":"otp-req-a1b2c3d4","expires_in_seconds":600,"masked_mobile":"+91XXXXXX3210","message":"OTP sent successfully"}}}},"401":{"description":"**DSP-013 INVALID_DEVICE_TOKEN** (HTTP 401) — Bearer token missing, expired or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error_code":"DSP-013","error":"INVALID_DEVICE_TOKEN","message":"Bearer token missing, expired or invalid","trace_id":"trace-20260612-abc12345","timestamp":"2026-06-12T10:30:00Z"}}}},"404":{"description":"**DSP-012 DEVICE_NOT_FOUND** (HTTP 404) — device_id not in registry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error_code":"DSP-012","error":"DEVICE_NOT_FOUND","message":"device_id not in registry","trace_id":"trace-20260612-abc12345","timestamp":"2026-06-12T10:30:00Z"}}}},"422":{"description":"**DSP-010 INVALID_MOBILE_NUMBER** (HTTP 422) — Not a valid +91 Indian mobile in E.164","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error_code":"DSP-010","error":"INVALID_MOBILE_NUMBER","message":"Not a valid +91 Indian mobile in E.164","trace_id":"trace-20260612-abc12345","timestamp":"2026-06-12T10:30:00Z"}}}},"429":{"description":"**DSP-011 OTP_RATE_LIMIT_EXCEEDED** (HTTP 429) — 5 OTPs/hour limit reached for this number","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error_code":"DSP-011","error":"OTP_RATE_LIMIT_EXCEEDED","message":"5 OTPs/hour limit reached for this number","trace_id":"trace-20260612-abc12345","timestamp":"2026-06-12T10:30:00Z"}}}}}}},"/user/verify-otp":{"post":{"tags":["Customer & OTP"],"summary":"Verify OTP","operationId":"verifyOtp","description":"Verifies the OTP, creates/updates the customer record, links customer ↔ device and returns a 30-day `user_token`. Maximum 3 attempts per OTP; then a 30-minute lockout.\n\n**Auth:** `device_token`.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["mobile_number","otp_code","request_id","device_id"],"properties":{"mobile_number":{"type":"string","example":"+919876543210"},"otp_code":{"type":"string","example":"123456"},"request_id":{"type":"string","example":"otp-req-a1b2c3d4"},"device_id":{"type":"string","format":"uuid"}}}}}},"responses":{"200":{"description":"OTP verified; user_token issued","content":{"application/json":{"example":{"success":true,"user_token":"eyJhbGciOiJIUzI1NiIs...","customer_id":"c1a2b3c4-5d6e-7f8a-9012-345678901234","token_expiry":"2026-07-12T00:00:00Z","is_new_customer":true,"message":"OTP verified successfully"}}}},"401":{"description":"**DSP-020 INVALID_OTP** (HTTP 401) — OTP does not match (or DSP-021 OTP_EXPIRED)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error_code":"DSP-020","error":"INVALID_OTP","message":"OTP does not match (or DSP-021 OTP_EXPIRED)","trace_id":"trace-20260612-abc12345","timestamp":"2026-06-12T10:30:00Z"}}}},"404":{"description":"**DSP-023 REQUEST_ID_NOT_FOUND** (HTTP 404) — No active OTP request for this request_id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error_code":"DSP-023","error":"REQUEST_ID_NOT_FOUND","message":"No active OTP request for this request_id","trace_id":"trace-20260612-abc12345","timestamp":"2026-06-12T10:30:00Z"}}}},"429":{"description":"**DSP-022 OTP_MAX_ATTEMPTS_EXCEEDED** (HTTP 429) — 3 failed attempts; locked 30 minutes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error_code":"DSP-022","error":"OTP_MAX_ATTEMPTS_EXCEEDED","message":"3 failed attempts; locked 30 minutes","trace_id":"trace-20260612-abc12345","timestamp":"2026-06-12T10:30:00Z"}}}}}}},"/warranty/register":{"post":{"tags":["Warranty"],"summary":"Register warranty","operationId":"registerWarranty","description":"Registers device warranty for the OTP-verified customer. Purchase date must not be in the future and must fall within 90 days of first activation; one active warranty per device; `retailer_code` (optional) must exist in the Retailer Master.\n\n**Auth:** `user_token`.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["device_id","purchase_date"],"properties":{"device_id":{"type":"string","format":"uuid"},"purchase_date":{"type":"string","format":"date","example":"2026-06-01"},"retailer_code":{"type":"string","example":"RET-MH-001"},"invoice_number":{"type":"string","example":"INV-2026-00456"},"purchase_city":{"type":"string","example":"Mumbai"}}}}}},"responses":{"201":{"description":"Warranty registered","content":{"application/json":{"example":{"success":true,"warranty_id":"w9x8y7z6-5432-1098-abcd-ef0987654321","warranty_start":"2026-06-01","warranty_expiry":"2027-06-01","warranty_period_months":12,"warranty_status":"active","message":"Warranty registered successfully"}}}},"404":{"description":"**DSP-034 DEVICE_NOT_FOUND** (HTTP 404) — device_id not in registry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error_code":"DSP-034","error":"DEVICE_NOT_FOUND","message":"device_id not in registry","trace_id":"trace-20260612-abc12345","timestamp":"2026-06-12T10:30:00Z"}}}},"409":{"description":"**DSP-030 DEVICE_ALREADY_HAS_WARRANTY** (HTTP 409) — Active warranty already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error_code":"DSP-030","error":"DEVICE_ALREADY_HAS_WARRANTY","message":"Active warranty already exists","trace_id":"trace-20260612-abc12345","timestamp":"2026-06-12T10:30:00Z"}}}},"422":{"description":"**DSP-031 PURCHASE_DATE_INVALID** (HTTP 422) — Future/invalid date (or DSP-032 outside 90-day window, DSP-033 unknown retailer)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error_code":"DSP-031","error":"PURCHASE_DATE_INVALID","message":"Future/invalid date (or DSP-032 outside 90-day window, DSP-033 unknown retailer)","trace_id":"trace-20260612-abc12345","timestamp":"2026-06-12T10:30:00Z"}}}}}}},"/ota/check-update":{"post":{"tags":["OTA"],"summary":"Check for firmware update","operationId":"checkUpdate","description":"Device polls for an eligible OTA release. Battery below 20% → `update_available:false` with reason `BATTERY_TOO_LOW`. On cellular networks only delta packages are offered. Download URL is a (simulated) 2-hour pre-signed link.\n\n**Auth:** `device_token`.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["device_id","current_fw_version","model_code"],"properties":{"device_id":{"type":"string","format":"uuid"},"current_fw_version":{"type":"string","example":"1.2.0"},"model_code":{"type":"string","example":"BOLTT-PH5G-2026"},"device_type":{"type":"string","example":"smartphone"},"battery_level":{"type":"integer","example":65},"network_type":{"type":"string","enum":["wifi","4g","5g","offline"]}}}}}},"responses":{"200":{"description":"Update decision (update_available true/false — battery-low and no-update cases also return 200)","content":{"application/json":{"examples":{"available":{"value":{"update_available":true,"update_id":"ota-upd-20260601-001","target_fw_version":"1.3.0","package_type":"delta","download_url":"https://boltt-backend.rad0.dev/ota/packages/...","file_size_bytes":52428800,"sha256_checksum":"e3b0c44298fc1c149af...","kms_signature":"AQIDBA...","release_notes":"Performance improvements and bug fixes.","url_expires_at":"2026-06-12T14:00:00Z"}},"batteryLow":{"value":{"update_available":false,"reason":"BATTERY_TOO_LOW","message":"Battery at 15% is below the 20% minimum required for an OTA update."}},"none":{"value":{"update_available":false,"reason":"NO_UPDATE_AVAILABLE","message":"No firmware newer than 1.3.0 is currently rolling out for BOLTT-PH5G-2026."}}}}}},"404":{"description":"**DSP-040 DEVICE_NOT_FOUND** (HTTP 404) — device_id does not exist in registry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error_code":"DSP-040","error":"DEVICE_NOT_FOUND","message":"device_id does not exist in registry","trace_id":"trace-20260612-abc12345","timestamp":"2026-06-12T10:30:00Z"}}}}}}},"/ota/report-status":{"post":{"tags":["OTA"],"summary":"Report OTA install status","operationId":"reportOtaStatus","description":"Device reports installation outcome. `installed_fw_version` required on success; `error_code` required otherwise. One report per device per update — duplicates return DSP-051.\n\n**Auth:** `device_token`.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["device_id","update_id","status"],"properties":{"device_id":{"type":"string","format":"uuid"},"update_id":{"type":"string","example":"ota-upd-20260601-001"},"status":{"type":"string","enum":["success","failed","aborted","checksum_error","signature_error","insufficient_storage"]},"installed_fw_version":{"type":"string","example":"1.3.0"},"install_duration_seconds":{"type":"integer","example":247},"error_code":{"type":"string","nullable":true},"error_message":{"type":"string","nullable":true}}}}}},"responses":{"200":{"description":"Status recorded","content":{"application/json":{"example":{"success":true,"message":"OTA status recorded","next_check_in_hours":24}}}},"404":{"description":"**DSP-050 UPDATE_ID_NOT_FOUND** (HTTP 404) — OTA release ID not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error_code":"DSP-050","error":"UPDATE_ID_NOT_FOUND","message":"OTA release ID not found","trace_id":"trace-20260612-abc12345","timestamp":"2026-06-12T10:30:00Z"}}}},"409":{"description":"**DSP-051 STATUS_ALREADY_REPORTED** (HTTP 409) — This device already reported for this update","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error_code":"DSP-051","error":"STATUS_ALREADY_REPORTED","message":"This device already reported for this update","trace_id":"trace-20260612-abc12345","timestamp":"2026-06-12T10:30:00Z"}}}},"422":{"description":"**DSP-052 INVALID_STATUS_VALUE** (HTTP 422) — status not in the allowed set","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error_code":"DSP-052","error":"INVALID_STATUS_VALUE","message":"status not in the allowed set","trace_id":"trace-20260612-abc12345","timestamp":"2026-06-12T10:30:00Z"}}}}}}},"/device/telemetry":{"post":{"tags":["Telemetry & Health"],"summary":"Submit telemetry","operationId":"submitTelemetry","description":"Single event (flat body) or batch (`{ \"device_id\": ..., \"events\": [...] }`, max 10). Ranges: battery 0–100, temp −20…80 °C, CPU 0–100.\n\n**Auth:** `device_token`.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["device_id"],"properties":{"device_id":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"},"battery_level":{"type":"integer","example":78},"battery_temp":{"type":"number","example":32.5},"cpu_usage":{"type":"integer","example":23},"memory_free_mb":{"type":"integer","example":1840},"storage_free_gb":{"type":"number","example":48.2},"network_type":{"type":"string","enum":["wifi","4g","5g","offline"]},"signal_strength":{"type":"integer","example":-85},"fw_version":{"type":"string","example":"1.3.0"},"events":{"type":"array","description":"Optional batch form (max 10)","items":{"type":"object"}}}}}}},"responses":{"200":{"description":"Telemetry recorded","content":{"application/json":{"example":{"success":true,"message":"Telemetry recorded (1 event)"}}}},"404":{"description":"**DSP-061 DEVICE_NOT_FOUND** (HTTP 404) — device_id not in registry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error_code":"DSP-061","error":"DEVICE_NOT_FOUND","message":"device_id not in registry","trace_id":"trace-20260612-abc12345","timestamp":"2026-06-12T10:30:00Z"}}}},"422":{"description":"**DSP-060 INVALID_TELEMETRY_PAYLOAD** (HTTP 422) — Field range/enum violations — see details[]","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error_code":"DSP-060","error":"INVALID_TELEMETRY_PAYLOAD","message":"Field range/enum violations — see details[]","trace_id":"trace-20260612-abc12345","timestamp":"2026-06-12T10:30:00Z"}}}}}}},"/device/heartbeat":{"post":{"tags":["Telemetry & Health"],"summary":"Heartbeat ping","operationId":"heartbeat","description":"Lightweight ping every N hours. Updates `last_seen` and `current_fw_version`; returns current configuration. Blacklisted devices receive DSP-071 (403).\n\n**Auth:** `device_token`.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["device_id","fw_version","sdk_version","battery_level","network_type"],"properties":{"device_id":{"type":"string","format":"uuid"},"fw_version":{"type":"string","example":"1.3.0"},"sdk_version":{"type":"string","example":"1.2.3"},"battery_level":{"type":"integer","example":82},"network_type":{"type":"string","enum":["wifi","4g","5g","offline"]}}}}}},"responses":{"200":{"description":"Heartbeat accepted; configuration returned","content":{"application/json":{"example":{"success":true,"configuration_updated":false,"configuration":{"heartbeat_interval_seconds":21600,"telemetry_enabled":true,"crash_report_enabled":true,"ota_check_interval_hours":24}}}}},"403":{"description":"**DSP-071 DEVICE_BLACKLISTED** (HTTP 403) — Device has been blacklisted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error_code":"DSP-071","error":"DEVICE_BLACKLISTED","message":"Device has been blacklisted","trace_id":"trace-20260612-abc12345","timestamp":"2026-06-12T10:30:00Z"}}}},"404":{"description":"**DSP-070 DEVICE_NOT_FOUND** (HTTP 404) — device_id not in registry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error_code":"DSP-070","error":"DEVICE_NOT_FOUND","message":"device_id not in registry","trace_id":"trace-20260612-abc12345","timestamp":"2026-06-12T10:30:00Z"}}}}}}},"/device/crash-report":{"post":{"tags":["Telemetry & Health"],"summary":"Upload crash report","operationId":"crashReport","description":"Uploads a crash report. `stack_trace` over 50,000 chars → DSP-080 (413) with a pre-signed upload URL. `crash_timestamp` must not be in the future.\n\n**Auth:** `device_token`.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["device_id","crash_type","package_name","crash_timestamp","stack_trace"],"properties":{"device_id":{"type":"string","format":"uuid"},"crash_type":{"type":"string","enum":["fatal","anr","native","java"]},"package_name":{"type":"string","example":"com.boltt.launcher"},"crash_timestamp":{"type":"string","format":"date-time"},"fw_version":{"type":"string","example":"1.3.0"},"android_version":{"type":"string","example":"13.0"},"free_memory_mb":{"type":"integer","example":342},"stack_trace":{"type":"string","example":"java.lang.NullPointerException\n   at com.boltt.launcher.MainActivity..."}}}}}},"responses":{"201":{"description":"Crash report stored","content":{"application/json":{"example":{"success":true,"crash_id":"crsh-uuid-1234-5678-90ab","message":"Crash report received"}}}},"413":{"description":"**DSP-080 STACK_TRACE_TOO_LARGE** (HTTP 413) — Use the returned pre-signed URL for large traces","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error_code":"DSP-080","error":"STACK_TRACE_TOO_LARGE","message":"Use the returned pre-signed URL for large traces","trace_id":"trace-20260612-abc12345","timestamp":"2026-06-12T10:30:00Z"}}}},"422":{"description":"**DSP-081 INVALID_CRASH_TYPE** (HTTP 422) — crash_type not in fatal | anr | native | java","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error_code":"DSP-081","error":"INVALID_CRASH_TYPE","message":"crash_type not in fatal | anr | native | java","trace_id":"trace-20260612-abc12345","timestamp":"2026-06-12T10:30:00Z"}}}}}}},"/device/configuration":{"get":{"tags":["Device Lifecycle"],"summary":"Get remote configuration","operationId":"getConfiguration","description":"Returns the model-specific remote configuration: intervals, log level and feature flags.\n\n**Auth:** `device_token`; `device_id` must match the token.","security":[{"bearerAuth":[]}],"parameters":[{"name":"device_id","in":"query","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Current configuration","content":{"application/json":{"example":{"success":true,"device_id":"d8f3a1c2-4e56-7890-abcd-ef1234567890","configuration":{"heartbeat_interval_seconds":21600,"telemetry_enabled":true,"crash_report_enabled":true,"ota_check_interval_hours":24,"max_log_level":"warn","feature_flags":{"advanced_telemetry":false,"beta_ota":false}},"config_version":"v1.4","updated_at":"2026-05-30T12:00:00Z"}}}},"401":{"description":"**DSP-091 INVALID_DEVICE_TOKEN** (HTTP 401) — Token/device mismatch","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error_code":"DSP-091","error":"INVALID_DEVICE_TOKEN","message":"Token/device mismatch","trace_id":"trace-20260612-abc12345","timestamp":"2026-06-12T10:30:00Z"}}}},"404":{"description":"**DSP-090 DEVICE_NOT_FOUND** (HTTP 404) — device_id not in registry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error_code":"DSP-090","error":"DEVICE_NOT_FOUND","message":"device_id not in registry","trace_id":"trace-20260612-abc12345","timestamp":"2026-06-12T10:30:00Z"}}}}}}},"/device/profile":{"get":{"tags":["Device Lifecycle"],"summary":"Get device profile","operationId":"getProfile","description":"Complete device profile with masked customer linkage and warranty status. `customer`/`warranty` are `null` when not linked/registered.\n\n**Auth:** `device_token` (own device) or `user_token` (linked device).","security":[{"bearerAuth":[]}],"parameters":[{"name":"device_id","in":"query","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Profile","content":{"application/json":{"example":{"success":true,"device":{"device_id":"d8f3a1c2-4e56-7890-abcd-ef1234567890","model_name":"Boltt Phantom 5G","device_type":"smartphone","activation_status":"active","activation_date":"2026-06-01T08:00:00Z","current_fw_version":"1.3.0","last_seen":"2026-06-12T10:30:00Z"},"customer":{"customer_id":"c1a2b3c4-5d6e-7f8a-9012-345678901234","mobile_number":"+91XXXXXX3210"},"warranty":{"warranty_id":"w9x8y7z6-5432-1098-abcd-ef0987654321","warranty_status":"active","warranty_expiry":"2027-06-01"}}}}},"403":{"description":"**DSP-101 UNAUTHORIZED_ACCESS** (HTTP 403) — Token does not own / is not linked to this device","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error_code":"DSP-101","error":"UNAUTHORIZED_ACCESS","message":"Token does not own / is not linked to this device","trace_id":"trace-20260612-abc12345","timestamp":"2026-06-12T10:30:00Z"}}}},"404":{"description":"**DSP-100 DEVICE_NOT_FOUND** (HTTP 404) — device_id not in registry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error_code":"DSP-100","error":"DEVICE_NOT_FOUND","message":"device_id not in registry","trace_id":"trace-20260612-abc12345","timestamp":"2026-06-12T10:30:00Z"}}}}}}},"/device/unregister":{"post":{"tags":["Device Lifecycle"],"summary":"Unregister device (admin)","operationId":"unregisterDevice","description":"Deactivates a device (factory reset, resale, replacement). `reported_stolen` blacklists the IMEI instead. Device tokens are revoked immediately; an audit log entry is written.\n\n**Auth:** `admin_token` with `device:unregister` permission.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["device_id","reason"],"properties":{"device_id":{"type":"string","format":"uuid"},"reason":{"type":"string","enum":["customer_resale","factory_reset","device_replacement","reported_stolen","admin_action"]},"initiated_by":{"type":"string","example":"admin@boltt.com"},"notes":{"type":"string"}}}}}},"responses":{"200":{"description":"Device deactivated (or blacklisted for reported_stolen)","content":{"application/json":{"example":{"success":true,"device_id":"d8f3a1c2-4e56-7890-abcd-ef1234567890","status":"deactivated","deactivated_at":"2026-06-12T11:00:00Z","message":"Device unregistered successfully"}}}},"403":{"description":"**DSP-112 INSUFFICIENT_PERMISSIONS** (HTTP 403) — Admin role required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error_code":"DSP-112","error":"INSUFFICIENT_PERMISSIONS","message":"Admin role required","trace_id":"trace-20260612-abc12345","timestamp":"2026-06-12T10:30:00Z"}}}},"404":{"description":"**DSP-110 DEVICE_NOT_FOUND** (HTTP 404) — device_id not in registry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error_code":"DSP-110","error":"DEVICE_NOT_FOUND","message":"device_id not in registry","trace_id":"trace-20260612-abc12345","timestamp":"2026-06-12T10:30:00Z"}}}},"409":{"description":"**DSP-111 DEVICE_ALREADY_DEACTIVATED** (HTTP 409) — Already deactivated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error_code":"DSP-111","error":"DEVICE_ALREADY_DEACTIVATED","message":"Already deactivated","trace_id":"trace-20260612-abc12345","timestamp":"2026-06-12T10:30:00Z"}}}}}}},"/auth/admin/login":{"post":{"tags":["Admin"],"summary":"Admin login (UAT token issuance)","operationId":"adminLogin","description":"Issues an 8-hour `admin_token`. In the spec admin tokens are issued by the DSP team per request — this endpoint plays that role in UAT. Seeded credentials are listed in the [credentials report](/report).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","password"],"properties":{"email":{"type":"string","example":"admin@boltt.com"},"password":{"type":"string"}}}}}},"responses":{"200":{"description":"admin_token issued","content":{"application/json":{"example":{"success":true,"admin_token":"eyJhbGciOiJIUzI1NiIs...","role":"release_manager","permissions":["device:unregister","ota:approve"],"token_expiry":"2026-06-12T19:00:00Z","message":"Admin authenticated successfully"}}}},"401":{"description":"**DSP-120 INVALID_ADMIN_CREDENTIALS** (HTTP 401) — Email or password incorrect","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"success":false,"error_code":"DSP-120","error":"INVALID_ADMIN_CREDENTIALS","message":"Email or password incorrect","trace_id":"trace-20260612-abc12345","timestamp":"2026-06-12T10:30:00Z"}}}}}}},"/health":{"get":{"tags":["Platform"],"summary":"Service health","operationId":"health","responses":{"200":{"description":"Service and database status","content":{"application/json":{"example":{"success":true,"service":"boltt-dsp-uat","version":"1.0.0","database":"up","uptime_seconds":12345,"timestamp":"2026-06-12T10:30:00Z"}}}}}}}}}