{"ok":true,"message":"Tasfia AI API","endpoints":{"health":"GET /health (no auth)","openaiStatus":"GET /api/openai/status (Bearer token)","extractSak":"POST /api/extract-sak (Bearer; PDF/image; response includes relevantDocument + extracted.documentClassification)","extractImageText":"POST /api/extract-image-text (same as extract-sak, backward compatible)","nearbyServices":"GET|POST /api/nearby-services (Bearer; required lat, lng; optional radiusKm, provider)","nearbyServicesStatus":"GET /api/nearby-services/status (Bearer; provider config)","newBid":"POST /api/new-bid (Laravel service key; JSON: bid_id, user_id, product_id, bid_price, product_title, product_img, auction_title; fans out product:update)","auctionStarted":"POST /api/product/auction-started (Laravel service key; JSON: { auction: { id, ... } })","auctionEnded":"POST /api/product/auction-ended (Laravel service key; JSON: { auction: { id, ... } })","nafathCallback":"POST /api/nafath-callback (Laravel → Socket.IO fan-out; JSON: status, transId, PersonId, optional user, token)"},"sockets":{"connect":"WebSocket to same host/port; optional auth.token (validated via getaccount when present; anonymous allowed for product rooms)","productSubscribe":"emit product:subscribe with { productId }","productUpdate":"listen product:update — types: new_bid (product lot)","auctionSubscribe":"emit auction:subscribe with { auctionId }","auctionUpdate":"listen auction:update — types: auction_started, auction_ended","nafathSubscribe":"emit nafath:subscribe with { transId }","nafathResult":"listen nafath:auth_result"},"auth":{"userRoutes":"Authorization: Bearer <user session token> or X-Access-Token (validated via Laravel getaccount)","backendRoutes":"X-Tasfia-Service-Key or Authorization: Bearer <TASFIA_BACKEND_SERVICE_KEY> (server-to-server only)"}}