openapi: 3.0.0 info: title: SiTukang API description: | Complete API Documentation for SiTukang - A Single Backend for Customers and Workers. Authentication is handled via RBAC with JWT access tokens. version: 1.0.0 servers: - url: https://xryz-gcw-situkang.hf.space/v1 description: Production Server (Hugging Face) - url: http://localhost:8080/v1 description: Local Development Server security: - BearerAuth: [] paths: # ========================================== # PART A: Authentication & General # ========================================== /auth/register: post: tags: [Authentication] summary: Register a new account description: Register a new customer (user) or worker. security: [] requestBody: required: true content: application/json: schema: type: object required: [full_name, email, phone, password, password_confirmation, role] properties: full_name: { type: string, example: Budi Santoso } email: { type: string, format: email, example: budi@email.com } phone: { type: string, example: "+6281234567890" } password: { type: string, format: password, example: SecureP@ss123 } password_confirmation: { type: string, format: password, example: SecureP@ss123 } role: { type: string, enum: [user, worker], example: user } latitude: { type: number, example: -7.257500 } longitude: { type: number, example: 112.752100 } address: { type: string, example: "Jl. Merdeka No. 12, Surabaya" } responses: '201': description: Registration successful content: application/json: schema: $ref: '#/components/schemas/AuthResponse' '409': description: Email already registered content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /auth/login: post: tags: [Authentication] summary: Login to account description: Authenticate user or worker and receive JWT access token. security: [] requestBody: required: true content: application/json: schema: type: object required: [email, password] properties: email: { type: string, format: email, example: budi@email.com } password: { type: string, format: password, example: SecureP@ss123 } responses: '200': description: Login successful content: application/json: schema: $ref: '#/components/schemas/AuthResponse' '401': description: Invalid email or password content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /auth/refresh: post: tags: [Authentication] summary: Refresh JWT token description: Rotate and refresh access token using refresh token. security: [] requestBody: required: true content: application/json: schema: type: object required: [refresh_token] properties: refresh_token: { type: string, example: dGhpcyBpcyBhIHJlZnJlc2ggdG9rZW4... } responses: '200': description: Token refreshed content: application/json: schema: $ref: '#/components/schemas/AuthResponse' /auth/logout: post: tags: [Authentication] summary: Logout description: Invalidate active refresh token. responses: '200': description: Logout successful content: application/json: schema: type: object properties: status: { type: string, example: success } message: { type: string, example: Berhasil logout } /auth/forgot-password: post: tags: [Authentication] summary: Forgot password request description: Send password reset link to user email. security: [] requestBody: required: true content: application/json: schema: type: object required: [email] properties: email: { type: string, format: email, example: budi@email.com } responses: '200': description: Reset link sent content: application/json: schema: type: object properties: status: { type: string, example: success } message: { type: string, example: Link reset password telah dikirim ke email Anda } /auth/reset-password: post: tags: [Authentication] summary: Reset password description: Reset password using token from email. security: [] requestBody: required: true content: application/json: schema: type: object required: [token, password, password_confirmation] properties: token: { type: string, example: reset-token-from-email } password: { type: string, example: NewSecureP@ss456 } password_confirmation: { type: string, example: NewSecureP@ss456 } responses: '200': description: Password reset successful content: application/json: schema: type: object properties: status: { type: string, example: success } message: { type: string, example: Password berhasil direset } # ========================================== # PART B: User Profile # ========================================== /users/me: get: tags: [User Profile] summary: Get own profile description: Retrieve own profile details. responses: '200': description: Profile retrieved content: application/json: schema: type: object properties: status: { type: string, example: success } data: { $ref: '#/components/schemas/UserProfile' } put: tags: [User Profile] summary: Update profile description: Update profile details. requestBody: required: true content: application/json: schema: type: object properties: full_name: { type: string, example: Budi Santoso } phone: { type: string, example: "+6281234567890" } address: { type: string, example: "Jl. Merdeka No. 14, Surabaya" } latitude: { type: number, example: -7.257600 } longitude: { type: number, example: 112.752200 } responses: '200': description: Profile updated content: application/json: schema: type: object properties: status: { type: string, example: success } message: { type: string, example: Profil berhasil diperbarui } /users/me/avatar: put: tags: [User Profile] summary: Upload avatar description: Upload profile photo. requestBody: required: true content: multipart/form-data: schema: type: object required: [avatar] properties: avatar: { type: string, format: binary, description: Image file (jpg/png, max 5MB) } responses: '200': description: Avatar uploaded content: application/json: schema: type: object properties: status: { type: string, example: success } message: { type: string, example: Foto profil berhasil diperbarui } data: type: object properties: avatar_url: { type: string, example: "https://cdn.situkang.id/avatars/budi_001_v2.jpg" } /users/me/location: put: tags: [User Profile] summary: Update current location description: Update coordinates and address. requestBody: required: true content: application/json: schema: type: object required: [latitude, longitude] properties: latitude: { type: number, example: -7.257500 } longitude: { type: number, example: 112.752100 } address: { type: string, example: "Jl. Merdeka No. 12, Surabaya" } responses: '200': description: Location updated # ========================================== # PART C: Customer (User) Endpoints # ========================================== /home: get: tags: [Customer Home] summary: Get User Home summary description: Fetch categories, suggests, active order banner, promo, and featured workers. parameters: - name: latitude in: query required: true schema: { type: number } - name: longitude in: query required: true schema: { type: number } responses: '200': description: Summary retrieved /categories: get: tags: [Customer Services] summary: List Categories description: Retrieve service categories. parameters: - name: page in: query schema: { type: integer, default: 1 } - name: per_page in: query schema: { type: integer, default: 20 } responses: '200': description: Categories retrieved /categories/{category_id}/services: get: tags: [Customer Services] summary: Services in Category description: Retrieve all active services within a specific category. parameters: - name: category_id in: path required: true schema: { type: string } responses: '200': description: Services retrieved /workers/nearby: get: tags: [Customer Workers] summary: Find Nearby Workers description: Search and filter workers closest to user's location. parameters: - name: latitude in: query required: true schema: { type: number } - name: longitude in: query required: true schema: { type: number } - name: radius_km in: query schema: { type: number, default: 10 } - name: category_id in: query schema: { type: string } - name: service_id in: query schema: { type: string } - name: min_rating in: query schema: { type: number } - name: sort_by in: query schema: { type: string, enum: [distance, rating, price, completed_jobs], default: distance } - name: sort_order in: query schema: { type: string, enum: [asc, desc], default: asc } - name: page in: query schema: { type: integer, default: 1 } - name: per_page in: query schema: { type: integer, default: 10 } responses: '200': description: Workers retrieved /workers/search: get: tags: [Customer Workers] summary: Search Workers description: Search workers by keyword (name, specialization, damage type). parameters: - name: q in: query required: true schema: { type: string } - name: latitude in: query required: true schema: { type: number } - name: longitude in: query required: true schema: { type: number } - name: radius_km in: query schema: { type: number } - name: page in: query schema: { type: integer } - name: per_page in: query schema: { type: integer } responses: '200': description: Search results retrieved /workers/{worker_id}: get: tags: [Customer Workers] summary: Worker Detailed Profile description: Retrieve details of a specific worker. parameters: - name: worker_id in: path required: true schema: { type: string } responses: '200': description: Worker detail retrieved /workers/{worker_id}/reviews: get: tags: [Customer Workers] summary: Worker Reviews description: List rating reviews given to a worker. parameters: - name: worker_id in: path required: true schema: { type: string } responses: '200': description: Worker reviews retrieved /workers/{worker_id}/services: get: tags: [Customer Workers] summary: Worker Custom Services description: List custom services offered by a worker. parameters: - name: worker_id in: path required: true schema: { type: string } responses: '200': description: Worker custom services retrieved /orders: post: tags: [Customer Orders] summary: Create Order description: Customer places a new match booking request. requestBody: required: true content: application/json: schema: type: object required: [worker_id, service_id, address, latitude, longitude, problem_description] properties: worker_id: { type: string } service_id: { type: string } address: { type: string } latitude: { type: number } longitude: { type: number } urgency: { type: string, enum: [normal, urgent], default: normal } problem_description: { type: string } photos: { type: array, items: { type: string } } responses: '201': description: Order created get: tags: [Customer Orders] summary: List Orders description: Get active/history orders of customer. parameters: - name: status in: query schema: { type: string } - name: page in: query schema: { type: integer } - name: per_page in: query schema: { type: integer } responses: '200': description: Orders list retrieved /orders/{order_id}: get: tags: [Customer Orders] summary: Get Order Detail description: Get detail data of an order. parameters: - name: order_id in: path required: true schema: { type: string } responses: '200': description: Order details retrieved /orders/{order_id}/cancel: post: tags: [Customer Orders] summary: Cancel Order description: Cancel order booking. parameters: - name: order_id in: path required: true schema: { type: string } requestBody: required: true content: application/json: schema: type: object required: [cancel_reason] properties: cancel_reason: { type: string, enum: [changed_mind, found_other_worker, too_long, other] } notes: { type: string } responses: '200': description: Order cancelled successfully /orders/{order_id}/tracking: get: tags: [Customer Tracking] summary: Tracking Info description: Get live order steps tracking logs. parameters: - name: order_id in: path required: true schema: { type: string } responses: '200': description: Tracking logs retrieved /orders/{order_id}/tracking/location: get: tags: [Customer Tracking] summary: Live Worker Location (Poll) description: Get worker's current coordinates. parameters: - name: order_id in: path required: true schema: { type: string } responses: '200': description: Worker location retrieved /orders/{order_id}/purchases: get: tags: [Customer Purchases] summary: List Purchases description: List material/tool additions of the job. parameters: - name: order_id in: path required: true schema: { type: string } responses: '200': description: Purchases list retrieved /orders/{order_id}/purchases/{purchase_id}: get: tags: [Customer Purchases] summary: Purchase Detail description: Retrieve detail of a single purchase item. parameters: - name: order_id in: path required: true schema: { type: string } - name: purchase_id in: path required: true schema: { type: string } responses: '200': description: Purchase detail retrieved /orders/{order_id}/purchases/{purchase_id}/approve: patch: tags: [Customer Purchases] summary: Approve Purchase description: Approve a submitted purchase item. parameters: - name: order_id in: path required: true schema: { type: string } - name: purchase_id in: path required: true schema: { type: string } responses: '200': description: Purchase approved /orders/{order_id}/purchases/{purchase_id}/reject: patch: tags: [Customer Purchases] summary: Reject Purchase description: Reject a submitted purchase item. parameters: - name: order_id in: path required: true schema: { type: string } - name: purchase_id in: path required: true schema: { type: string } requestBody: required: true content: application/json: schema: type: object required: [reject_reason] properties: reject_reason: { type: string } responses: '200': description: Purchase rejected /orders/{order_id}/purchases/{purchase_id}/clarify: patch: tags: [Customer Purchases] summary: Request Clarification description: Request clarify details about a purchase. parameters: - name: order_id in: path required: true schema: { type: string } - name: purchase_id in: path required: true schema: { type: string } requestBody: required: true content: application/json: schema: type: object required: [question] properties: question: { type: string } responses: '200': description: Clarification requested /orders/{order_id}/purchases/bulk-approve: patch: tags: [Customer Purchases] summary: Bulk Approve Purchases description: Approve multiple draft purchases together. parameters: - name: order_id in: path required: true schema: { type: string } requestBody: required: true content: application/json: schema: type: object required: [purchase_ids] properties: purchase_ids: { type: array, items: { type: string } } responses: '200': description: Purchases approved in bulk /orders/{order_id}/chat/messages: get: tags: [Customer Chat] summary: Chat History description: Get message history for the order chat thread. parameters: - name: order_id in: path required: true schema: { type: string } - name: before_id in: query schema: { type: string } - name: limit in: query schema: { type: integer } responses: '200': description: Messages retrieved post: tags: [Customer Chat] summary: Send Message description: Send chat message (text or image). parameters: - name: order_id in: path required: true schema: { type: string } requestBody: required: true content: application/json: schema: type: object required: [message_type, content] properties: message_type: { type: string, enum: [text, image] } content: { type: string } responses: '201': description: Message sent /orders/{order_id}/chat/read: patch: tags: [Customer Chat] summary: Mark Chat Read description: Mark incoming unread messages as read. parameters: - name: order_id in: path required: true schema: { type: string } responses: '200': description: Messages marked read /chats: get: tags: [Customer Chat] summary: List Conversations description: List active customer chats. responses: '200': description: Active chats list retrieved /orders/{order_id}/rating: post: tags: [Customer Rating] summary: Rate Worker description: Rate worker job completion. parameters: - name: order_id in: path required: true schema: { type: string } requestBody: required: true content: application/json: schema: type: object required: [rating, review_text] properties: rating: { type: integer, minimum: 1, maximum: 5 } review_text: { type: string } photos: { type: array, items: { type: string } } responses: '201': description: Rating submitted successfully get: tags: [Customer Rating] summary: Get Worker Rating description: Get review details submitted by user. parameters: - name: order_id in: path required: true schema: { type: string } responses: '200': description: Review detail retrieved /orders/{order_id}/invoice: get: tags: [Customer Payments] summary: Get Invoice description: Get billing details invoice. parameters: - name: order_id in: path required: true schema: { type: string } responses: '200': description: Invoice retrieved /orders/{order_id}/payment: post: tags: [Customer Payments] summary: Confirm Payment description: Pay invoice by cash, e-wallet, or bank transfer. parameters: - name: order_id in: path required: true schema: { type: string } requestBody: required: true content: application/json: schema: type: object required: [payment_method] properties: payment_method: { type: string, enum: [cash, bank_transfer, ewallet] } transaction_proof_url: { type: string } responses: '200': description: Payment transaction complete content: application/json: schema: type: object properties: status: { type: string, example: success } data: type: object properties: payment_id: { type: string, example: "9f9a4a7b-3b3d-4c3e-8c3d-3b3d4c3e8c3d" } order_id: { type: string, example: "8e8a4a7b-2b2d-3c3e-7c3d-2b2d3c3e7c3d" } invoice_id: { type: string, example: "7d7a4a7b-1b1d-2c2e-6c6d-1b1d2c2e6c6d" } amount: { type: integer, example: 150000 } payment_status: { type: string, example: "pending" } token: { type: string, example: "PAY-REF-ab12cd34" } redirect_url: { type: string, example: "http://localhost:8080/v1/payments/sandbox-checkout?payment_id=9f9a4a7b-3b3d-4c3e-8c3d-3b3d4c3e8c3d" } created_at: { type: string, format: date-time, example: "2026-05-30T10:15:30Z" } /orders/{order_id}/invoice/pdf: get: tags: [Customer Payments] summary: Download Invoice PDF description: Stream invoice PDF binary. parameters: - name: order_id in: path required: true schema: { type: string } responses: '200': description: PDF byte stream /payments/sandbox-checkout: get: tags: [Sandbox Payment Gateway] summary: Render Sandbox Checkout Page description: Serves an interactive mock payment completion screen in browser. parameters: - name: payment_id in: query required: true schema: { type: string } responses: '200': description: HTML Checkout Page content: text/html: schema: { type: string } /payments/sandbox-callback: post: tags: [Sandbox Payment Gateway] summary: Sandbox Payment Gateway Callback description: Webhook simulation that instantly processes checkout status transitions. requestBody: required: true content: application/json: schema: type: object required: [payment_id, status] properties: payment_id: { type: string, example: "9f9a4a7b-3b3d-4c3e-8c3d-3b3d4c3e8c3d" } status: { type: string, enum: [success, failed], example: success } responses: '200': description: Webhook processed content: application/json: schema: type: object properties: status: { type: string, example: success } message: { type: string, example: "Pembayaran sandbox sukses diproses" } data: type: object properties: payment_id: { type: string, example: "9f9a4a7b-3b3d-4c3e-8c3d-3b3d4c3e8c3d" } order_id: { type: string, example: "8e8a4a7b-2b2d-3c3e-7c3d-2b2d3c3e7c3d" } payment_status: { type: string, example: "paid" } paid_at: { type: string, format: date-time, example: "2026-05-30T10:15:45Z" } /payments/midtrans-webhook: post: tags: [Sandbox Payment Gateway] summary: Midtrans Webhook Callback description: Callback webhook from Midtrans Sandbox to verify signature and capture/settle payment status. security: [] requestBody: required: true content: application/json: schema: type: object required: [order_id, status_code, gross_amount, signature_key, transaction_status] properties: transaction_time: { type: string, example: "2026-06-10 18:27:19" } transaction_status: { type: string, example: "settlement" } status_message: { type: string, example: "midtrans payment notification" } status_code: { type: string, example: "200" } signature_key: { type: string, example: "sha512_hash_here" } payment_type: { type: string, example: "credit_card" } order_id: { type: string, example: "9f9a4a7b-3b3d-4c3e-8c3d-3b3d4c3e8c3d" } merchant_id: { type: string, example: "G135002001" } gross_amount: { type: string, example: "150000.00" } fraud_status: { type: string, example: "accept" } currency: { type: string, example: "IDR" } responses: '200': description: Webhook processed successfully content: application/json: schema: type: object properties: status: { type: string, example: success } message: { type: string, example: "Webhook Midtrans sukses diproses" } data: type: object properties: payment_id: { type: string, example: "9f9a4a7b-3b3d-4c3e-8c3d-3b3d4c3e8c3d" } order_id: { type: string, example: "8e8a4a7b-2b2d-3c3e-7c3d-2b2d3c3e7c3d" } payment_status: { type: string, example: "paid" } paid_at: { type: string, format: date-time, example: "2026-06-10T18:27:19Z" } /orders/{order_id}/payment/sync: post: tags: [Customer Payments] summary: Sync Midtrans Payment Status description: Pull the latest payment status from Midtrans Sandbox for a given order and update the local database. parameters: - name: order_id in: path required: true schema: { type: string } responses: '200': description: Status synchronized successfully content: application/json: schema: type: object properties: status: { type: string, example: success } message: { type: string, example: "Status pembayaran berhasil disinkronisasi" } data: type: object properties: payment_id: { type: string, example: "9f9a4a7b-3b3d-4c3e-8c3d-3b3d4c3e8c3d" } order_id: { type: string, example: "8e8a4a7b-2b2d-3c3e-7c3d-2b2d3c3e7c3d" } payment_status: { type: string, example: "paid" } paid_at: { type: string, format: date-time, example: "2026-06-10T18:27:19Z" } /knowledge/articles: get: tags: [Knowledge Base] summary: List Articles description: Retrieve guides and helpful articles. security: [] responses: '200': description: Articles retrieved /knowledge/articles/{id}: get: tags: [Knowledge Base] summary: Article Detail description: Get single article content. security: [] parameters: - name: id in: path required: true schema: { type: string } responses: '200': description: Article retrieved /knowledge/faq: get: tags: [Knowledge Base] summary: List FAQ description: Retrieve standard FAQs. security: [] responses: '200': description: FAQs retrieved /notifications: get: tags: [Notifications] summary: List Notifications description: Retrieve own notifications list. responses: '200': description: Notifications retrieved /notifications/{id}/read: patch: tags: [Notifications] summary: Mark Notification Read description: Mark a specific notification log read. parameters: - name: id in: path required: true schema: { type: string } responses: '200': description: Notification read updated /notifications/read-all: patch: tags: [Notifications] summary: Mark All Read description: Mark all notifications read. responses: '200': description: Action complete # ========================================== # PART D: Worker Endpoints # ========================================== /worker/profile: get: tags: [Worker Profile] summary: Get Worker Profile description: Retrieve detailed worker profile fields. responses: '200': description: Profile retrieved put: tags: [Worker Profile] summary: Update Worker Profile description: Update specialties, cover photos, or bio data. responses: '200': description: Profile updated /worker/profile/cover-photo: put: tags: [Worker Profile] summary: Cover Photo Upload description: Upload banner picture background for profile page. responses: '200': description: Photo updated /worker/profile/verification: post: tags: [Worker Profile] summary: Submit Verification Docs description: Onboarding KTP, SKCK, and certs. responses: '201': description: Document logs submitted get: tags: [Worker Profile] summary: Get Onboarding Status description: Check verification screening status. responses: '200': description: Onboarding status retrieved /worker/home: get: tags: [Worker Dashboard] summary: Worker Home Dashboard description: Get active orders, income analytics, acceptance rates. responses: '200': description: Analytics retrieved /worker/availability: patch: tags: [Worker Dashboard] summary: Toggle Availability description: Turn on/off online search matching banner. requestBody: required: true content: application/json: schema: type: object required: [is_available] properties: is_available: { type: boolean } responses: '200': description: Status complete /worker/orders/incoming: get: tags: [Worker Orders] summary: List Incoming Offers description: Matched job booking listings nearby. responses: '200': description: List retrieved /worker/orders/incoming/{id}: get: tags: [Worker Orders] summary: Incoming Offer Detail description: Retrieve offer coordinates and details. parameters: - name: id in: path required: true schema: { type: string } responses: '200': description: Offer detail retrieved /worker/orders/{id}/accept: post: tags: [Worker Orders] summary: Accept Offer description: Lock worker en-route to start arrival travel. parameters: - name: id in: path required: true schema: { type: string } responses: '200': description: Offer accepted /worker/orders/{id}/reject: post: tags: [Worker Orders] summary: Reject Offer description: Reject matching request order. parameters: - name: id in: path required: true schema: { type: string } requestBody: required: true content: application/json: schema: type: object required: [reject_reason] properties: reject_reason: { type: string, enum: [busy, too_far, not_my_expertise, personal, other] } responses: '200': description: Offer rejected /worker/orders: get: tags: [Worker Orders] summary: List Worker Orders description: List all history/active worker orders. responses: '200': description: List retrieved /worker/orders/{id}: get: tags: [Worker Orders] summary: Order Detail (Worker View) description: Billing breakdown of order for worker. parameters: - name: id in: path required: true schema: { type: string } responses: '200': description: Details retrieved /worker/orders/{id}/status: patch: tags: [Worker Orders] summary: Update Job Status description: Progress job order status (on_the_way -> arrived -> in_progress -> work_paused -> completed). parameters: - name: id in: path required: true schema: { type: string } requestBody: required: true content: application/json: schema: type: object required: [status] properties: status: { type: string, enum: [on_the_way, arrived, in_progress, work_paused, completed] } responses: '200': description: Status updated /worker/orders/{id}/generate-invoice: post: tags: [Worker Orders] summary: Generate Invoice description: Save batch materials list, calculate total costs, freeze pricing, and generate invoice. parameters: - name: id in: path required: true schema: { type: string } requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/GenerateInvoiceInput' responses: '201': description: Invoice generated successfully /worker/orders/{id}/purchases: post: tags: [Worker Purchases] summary: Add Purchase description: Manually append material expense. parameters: - name: id in: path required: true schema: { type: string } requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/PurchaseInput' responses: '201': description: Item drafted /worker/orders/{id}/purchases/ai-process: post: tags: [Worker Purchases] summary: AI process raw input description: Parse unstructured worker notes text to fields. parameters: - name: id in: path required: true schema: { type: string } requestBody: required: true content: application/json: schema: type: object required: [raw_input] properties: raw_input: { type: string, example: "beli pipa 2 meter sama lem pvc trus ongkos ojek" } responses: '200': description: AI parsed output items /worker/orders/{id}/purchases/receipt-scan: post: tags: [Worker Purchases] summary: Scan receipt (OCR + AI) description: Upload receipt picture and run OCR parse. parameters: - name: id in: path required: true schema: { type: string } requestBody: required: true content: multipart/form-data: schema: type: object required: [receipt] properties: receipt: { type: string, format: binary } responses: '200': description: OCR parsing complete /worker/orders/{id}/purchases/{purchase_id}: put: tags: [Worker Purchases] summary: Edit Purchase description: Modify fields of a draft purchase item. parameters: - name: id in: path required: true schema: { type: string } - name: purchase_id in: path required: true schema: { type: string } requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/PurchaseInput' responses: '200': description: Purchase updated delete: tags: [Worker Purchases] summary: Delete Purchase description: Remove draft purchase item. parameters: - name: id in: path required: true schema: { type: string } - name: purchase_id in: path required: true schema: { type: string } responses: '200': description: Purchase deleted successfully /worker/orders/{id}/purchases/{purchase_id}/submit: post: tags: [Worker Purchases] summary: Submit for approval description: Submit draft purchase to user. parameters: - name: id in: path required: true schema: { type: string } - name: purchase_id in: path required: true schema: { type: string } responses: '200': description: Submitted for approval /worker/orders/{id}/purchases/bulk-submit: post: tags: [Worker Purchases] summary: Bulk submit purchases description: Submit multiple draft items together. parameters: - name: id in: path required: true schema: { type: string } requestBody: required: true content: application/json: schema: type: object required: [purchase_ids] properties: purchase_ids: { type: array, items: { type: string } } responses: '200': description: Status updated /worker/orders/{id}/purchases/{purchase_id}/clarify-response: patch: tags: [Worker Purchases] summary: Respond to clarification description: Submit response text and updated details. parameters: - name: id in: path required: true schema: { type: string } - name: purchase_id in: path required: true schema: { type: string } requestBody: required: true content: application/json: schema: type: object required: [response] properties: response: { type: string } updated_item_name: { type: string } updated_reason: { type: string } responses: '200': description: Response submitted successfully /worker/orders/{id}/chat/messages: get: tags: [Worker Chat] summary: Chat History (Worker) description: Retrieve room messages. parameters: - name: id in: path required: true schema: { type: string } responses: '200': description: Messages retrieved post: tags: [Worker Chat] summary: Send Message (Worker) description: Send chat message. parameters: - name: id in: path required: true schema: { type: string } requestBody: required: true content: application/json: schema: type: object required: [message_type, content] properties: message_type: { type: string, enum: [text, image] } content: { type: string } responses: '201': description: Message sent /worker/orders/{id}/chat/read: patch: tags: [Worker Chat] summary: Mark chat read description: Mark incoming unread room messages read. parameters: - name: id in: path required: true schema: { type: string } responses: '200': description: Messages read status complete /worker/chats: get: tags: [Worker Chat] summary: List Conversations (Worker) description: List active worker conversations. responses: '200': description: Active chats list retrieved /worker/orders/{id}/customer-rating: post: tags: [Worker Rating] summary: Rate Customer description: Rate customer behavior/conduct. parameters: - name: id in: path required: true schema: { type: string } requestBody: required: true content: application/json: schema: type: object required: [rating, review_text] properties: rating: { type: integer, minimum: 1, maximum: 5 } review_text: { type: string } responses: '201': description: Customer rated successfully get: tags: [Worker Rating] summary: Get Customer Rating description: Get review details worker gave to customer. parameters: - name: id in: path required: true schema: { type: string } responses: '200': description: Rating retrieved /worker/history: get: tags: [Worker History & Stats] summary: Order History description: Retrieve order history logs. responses: '200': description: Completed jobs logs list retrieved /worker/statistics: get: tags: [Worker History & Stats] summary: Performance Statistics description: Retrieve ratings, acceptance rates, and analytics logs. parameters: - name: period in: query schema: { type: string, enum: [daily, weekly, monthly, yearly, all_time], default: monthly } responses: '200': description: Metrics logs retrieved /worker/wallet: get: tags: [Worker Wallet] summary: Wallet balance description: Check balance, pending earnings, and metrics. responses: '200': description: Wallet metrics retrieved /worker/wallet/transactions: get: tags: [Worker Wallet] summary: Transaction history description: List transaction logs of digital wallet. parameters: - name: type in: query schema: { type: string, enum: [earning, withdrawal, refund, bonus, fee] } - name: status in: query schema: { type: string, enum: [pending, completed, failed, cancelled] } - name: page in: query schema: { type: integer } - name: per_page in: query schema: { type: integer } responses: '200': description: Wallet transactions logs list retrieved /worker/wallet/withdraw: post: tags: [Worker Wallet] summary: Request withdrawal description: Request digital cash cashout. requestBody: required: true content: application/json: schema: type: object required: [amount, bank_name, account_number, account_holder_name] properties: amount: { type: integer, example: 5000000 } bank_name: { type: string, example: BCA } account_number: { type: string, example: "1234567890" } account_holder_name: { type: string, example: "Ahmad Jaelani" } notes: { type: string } responses: '201': description: Cashout log created /worker/location: put: tags: [Worker Location Updates] summary: Update location description: Update coordinates during transit. requestBody: required: true content: application/json: schema: type: object required: [latitude, longitude] properties: latitude: { type: number, example: -6.188000 } longitude: { type: number, example: 106.832000 } heading: { type: number } speed_kmh: { type: number } accuracy_meters: { type: number } order_id: { type: string } responses: '200': description: Coordinate log saved components: securitySchemes: BearerAuth: type: http scheme: bearer bearerFormat: JWT description: Bearer token containing user/worker claims. schemas: AuthResponse: type: object properties: status: { type: string, example: success } message: { type: string, example: Registrasi berhasil } data: type: object properties: user_id: { type: string } full_name: { type: string } email: { type: string } phone: { type: string } role: { type: string } access_token: { type: string } refresh_token: { type: string } token_type: { type: string, example: Bearer } expires_in: { type: integer, example: 3600 } ErrorResponse: type: object properties: status: { type: string, example: error } message: { type: string, example: Email sudah terdaftar } error_code: { type: string, example: EMAIL_ALREADY_EXISTS } UserProfile: type: object properties: user_id: { type: string } full_name: { type: string } email: { type: string } phone: { type: string } role: { type: string } avatar_url: { type: string } address: { type: string } latitude: { type: number } longitude: { type: number } is_active: { type: boolean } created_at: { type: string, format: date-time } Category: type: object properties: category_id: { type: string } name: { type: string } slug: { type: string } icon_url: { type: string } description: { type: string } Service: type: object properties: service_id: { type: string } category_id: { type: string } name: { type: string } slug: { type: string } description: { type: string } base_price: { type: number } price_unit: { type: string } WorkerNearby: type: object properties: worker_id: { type: string } full_name: { type: string } avatar_url: { type: string } specialization: { type: string } rating: { type: number } distance_km: { type: number } completed_jobs: { type: integer } is_verified: { type: boolean } is_available: { type: boolean } PurchaseInput: type: object required: [item_name, category, quantity, unit, unit_price, total_price] properties: item_name: { type: string, example: Pipa PVC 1/2 Inch } category: { type: string, enum: [material, alat, sparepart, bahan_bangunan, biaya_tambahan, lainnya], example: material } quantity: { type: number, example: 2 } unit: { type: string, example: meter } unit_price: { type: integer, example: 25000 } total_price: { type: integer, example: 50000 } reason: { type: string, example: Untuk mengganti pipa pecah } GenerateInvoiceInput: type: object properties: base_service_fee: { type: integer, example: 150000 } worker_notes: { type: string, example: Pekerjaan selesai. } total_material_cost: { type: integer, example: 50000 } purchases: type: array items: type: object required: [item_name, category, quantity, unit, unit_price, total_price] properties: purchase_id: { type: string, example: optional } item_name: { type: string, example: Pipa PVC } category: { type: string, enum: [material, alat, sparepart, bahan_bangunan, biaya_tambahan, lainnya], example: material } quantity: { type: number, example: 2 } unit: { type: string, example: meter } unit_price: { type: integer, example: 25000 } total_price: { type: integer, example: 50000 } reason: { type: string, example: Untuk mengganti pipa pecah }