{"openapi":"3.0.3","info":{"title":"MyTree API","version":"1.0.0","description":"Backend API server for the MyTree platform."},"servers":[{"url":"http://localhost:3001"}],"tags":[{"name":"System"},{"name":"Public"},{"name":"Auth"},{"name":"Donations"},{"name":"Profile"},{"name":"Plantings"},{"name":"QR"},{"name":"Certificates"},{"name":"Sync"},{"name":"Vendor"},{"name":"Admin"},{"name":"Admin Carbon"}],"paths":{"/api/health":{"get":{"tags":["System"],"summary":"Checks API and database connectivity.","description":"Checks API and database connectivity. Auth: Public.","operationId":"getHealth","responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/info":{"get":{"tags":["System"],"summary":"Returns API name, version, environment, and base URL.","description":"Returns API name, version, environment, and base URL. Auth: Public.","operationId":"getInfo","responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/stats/home":{"get":{"tags":["Public"],"summary":"Returns public home page planting statistics.","description":"Returns public home page planting statistics. Auth: Public.","operationId":"getStatsHome","responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/map/trees":{"get":{"tags":["Public"],"summary":"Returns planted tree locations for the map.","description":"Returns planted tree locations for the map. Auth: Public.","operationId":"getMapTrees","responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/auth/request-otp":{"post":{"tags":["Auth"],"summary":"Requests an OTP for phone or identifier login.","description":"Requests an OTP for phone or identifier login. Auth: Public.","operationId":"postAuthRequestOtp","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["identifier"],"properties":{"identifier":{"type":"string","description":"E.164 phone number, e.g. +8801712345678"}}}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/auth/verify-otp":{"post":{"tags":["Auth"],"summary":"Verifies OTP and returns auth tokens.","description":"Verifies OTP and returns auth tokens. Auth: Public.","operationId":"postAuthVerifyOtp","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["identifier","otp"],"properties":{"identifier":{"type":"string"},"otp":{"type":"string","minLength":6,"maxLength":6,"description":"6-digit OTP"}}}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/auth/refresh":{"post":{"tags":["Auth"],"summary":"Refreshes an access token.","description":"Refreshes an access token. Auth: Authenticated.","operationId":"postAuthRefresh","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["refreshToken"],"properties":{"refreshToken":{"type":"string"}}}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/auth/logout":{"post":{"tags":["Auth"],"summary":"Revokes the current refresh token.","description":"Revokes the current refresh token. Auth: Authenticated.","operationId":"postAuthLogout","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/donations/payments/initiate":{"post":{"tags":["Donations"],"summary":"Initiates an SSLCommerz hosted checkout for a donation.","description":"Initiates an SSLCommerz hosted checkout for a donation. Auth: Public.","operationId":"postDonationsPaymentsInitiate","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["amount"],"properties":{"amount":{"type":"integer","minimum":10},"method":{"type":"string","enum":["CARD","MOBILE_BANKING","INTERNET_BANKING"]},"source":{"type":"string","enum":["MOBILE_APP","WEB_PUBLIC"]},"customer":{"type":"object","properties":{"name":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string","format":"email"}}},"returnUrl":{"type":"string","format":"uri","description":"Optional absolute return URL for mobile/web handoff after callback"}}}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/donations/payments/status":{"get":{"tags":["Donations"],"summary":"Returns the current status of a donation payment.","description":"Returns the current status of a donation payment. Auth: Public.","operationId":"getDonationsPaymentsStatus","parameters":[{"name":"transactionId","in":"query","required":true,"description":"Donation transaction id returned during initiation","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/donations/payments/callback":{"get":{"tags":["Donations"],"summary":"Public browser callback endpoint for SSLCommerz payment redirects.","description":"Public browser callback endpoint for SSLCommerz payment redirects. Auth: Public.","operationId":"getDonationsPaymentsCallback","responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/donations/payments/ipn":{"post":{"tags":["Donations"],"summary":"Public SSLCommerz IPN endpoint for server-to-server payment updates.","description":"Public SSLCommerz IPN endpoint for server-to-server payment updates. Auth: Public.","operationId":"postDonationsPaymentsIpn","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/me":{"get":{"tags":["Profile"],"summary":"Returns the current user profile.","description":"Returns the current user profile. Auth: Authenticated.","operationId":"getMe","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"tags":["Profile"],"summary":"Updates the current user profile.","description":"Updates the current user profile. Auth: Authenticated.","operationId":"patchMe","security":[{"bearerAuth":[]}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":255},"email":{"type":"string","format":"email"},"avatarUrl":{"type":"string","format":"uri"},"metadata":{"type":"object","additionalProperties":true}}}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/me/role":{"get":{"tags":["Profile"],"summary":"Returns the current user role.","description":"Returns the current user role. Auth: Authenticated.","operationId":"getMeRole","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/plantings":{"post":{"tags":["Plantings"],"summary":"Creates a planting record from a QR plant.","description":"Creates a planting record from a QR plant. Auth: Authenticated.","operationId":"postPlantings","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["qrRecordId","planterName","planterPhone","lat","lng","plantedAt","photoUrls","requestId"],"properties":{"qrRecordId":{"type":"string","description":"QR record UUID or record code"},"qrRecordPlantId":{"type":"string","format":"uuid","description":"Required for batch QR with multiple available plants"},"planterName":{"type":"string","maxLength":255},"planterPhone":{"type":"string","maxLength":32},"treeName":{"type":"string","maxLength":255},"lat":{"type":"number","minimum":20,"maximum":26.5,"description":"Latitude within Bangladesh"},"lng":{"type":"number","minimum":88,"maximum":92.5,"description":"Longitude within Bangladesh"},"district":{"type":"string","maxLength":100},"area":{"type":"string","maxLength":255},"approximateLocation":{"type":"string","maxLength":255},"plantedAt":{"type":"string","format":"date-time"},"photoUrls":{"type":"array","items":{"type":"string","format":"uri"},"minItems":1,"maxItems":10},"requestId":{"type":"string","format":"uuid","description":"Client-generated idempotency key"},"notes":{"type":"string","maxLength":500},"metadata":{"type":"object","additionalProperties":true}}}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/plantings/{id}":{"get":{"tags":["Plantings"],"summary":"Returns a planting by ID.","description":"Returns a planting by ID. Auth: Authenticated.","operationId":"getPlantingsById","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/plantings/map":{"get":{"tags":["Plantings"],"summary":"Returns planting map markers with optional lat/lng/radius filter.","description":"Returns planting map markers with optional lat/lng/radius filter. Auth: Public.","operationId":"getPlantingsMap","parameters":[{"name":"lat","in":"query","required":false,"description":"Center latitude","schema":{"type":"number"}},{"name":"lng","in":"query","required":false,"description":"Center longitude","schema":{"type":"number"}},{"name":"radius","in":"query","required":false,"description":"Radius in km (default 25)","schema":{"type":"number","default":25}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/plantings/my":{"get":{"tags":["Plantings"],"summary":"Returns paginated list of the current user's plantings.","description":"Returns paginated list of the current user's plantings. Auth: Authenticated.","operationId":"getPlantingsMy","security":[{"bearerAuth":[]}],"parameters":[{"name":"page","in":"query","required":false,"description":"Zero-based page index","schema":{"type":"integer","default":0}},{"name":"size","in":"query","required":false,"description":"Page size (max 100)","schema":{"type":"integer","default":20,"maximum":100}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/qr/{recordId}":{"get":{"tags":["QR"],"summary":"Returns public QR record data.","description":"Returns public QR record data. Auth: Public.","operationId":"getQrByRecordId","parameters":[{"name":"recordId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/qr/{recordId}/details":{"get":{"tags":["QR"],"summary":"Returns detailed QR record information.","description":"Returns detailed QR record information. Auth: Public.","operationId":"getQrByRecordIdDetails","parameters":[{"name":"recordId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/qr/{recordId}/png":{"get":{"tags":["QR"],"summary":"Returns QR code PNG image.","description":"Returns QR code PNG image. Auth: Public.","operationId":"getQrByRecordIdPng","parameters":[{"name":"recordId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/certificates/{id}":{"get":{"tags":["Certificates"],"summary":"Returns certificate details.","description":"Returns certificate details. Auth: Public.","operationId":"getCertificatesById","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/certificates/{id}/history":{"get":{"tags":["Certificates"],"summary":"Returns certificate activity history.","description":"Returns certificate activity history. Auth: Public.","operationId":"getCertificatesByIdHistory","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/certificates/verify/{hash}":{"get":{"tags":["Certificates"],"summary":"Verifies a certificate by public hash.","description":"Verifies a certificate by public hash. Auth: Public.","operationId":"getCertificatesVerifyByHash","parameters":[{"name":"hash","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/certificates/me":{"get":{"tags":["Certificates"],"summary":"Returns certificates owned by the current user.","description":"Returns certificates owned by the current user. Auth: Authenticated.","operationId":"getCertificatesMe","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/certificates/mint":{"post":{"tags":["Certificates"],"summary":"Mints a certificate for an approved planting.","description":"Mints a certificate for an approved planting. Auth: Authenticated.","operationId":"postCertificatesMint","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["plantingId"],"properties":{"plantingId":{"type":"string","format":"uuid"}}}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sync/pull":{"post":{"tags":["Sync"],"summary":"Pulls server changes for offline sync.","description":"Pulls server changes for offline sync. Auth: Authenticated.","operationId":"postSyncPull","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"lastSyncAt":{"type":"string","format":"date-time","description":"Fetch changes after this timestamp. Omit to pull all."}}}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sync/push":{"post":{"tags":["Sync"],"summary":"Pushes client changes for offline sync.","description":"Pushes client changes for offline sync. Auth: Authenticated.","operationId":"postSyncPush","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"plantings":{"type":"array","maxItems":50,"items":{"type":"object","required":["requestId","qrRecordId","lat","lng","plantedAt"],"properties":{"requestId":{"type":"string"},"qrRecordId":{"type":"string","format":"uuid"},"lat":{"type":"number","minimum":20,"maximum":26.5},"lng":{"type":"number","minimum":88,"maximum":92.5},"district":{"type":"string"},"plantedAt":{"type":"string","format":"date-time"}}}}}}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/sync/status":{"get":{"tags":["Sync"],"summary":"Returns sync status for the current user.","description":"Returns sync status for the current user. Auth: Authenticated.","operationId":"getSyncStatus","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/vendor/qr/my":{"get":{"tags":["Vendor"],"summary":"Lists QR records created by the current vendor.","description":"Lists QR records created by the current vendor. Auth: Vendor.","operationId":"getVendorQrMy","security":[{"bearerAuth":[]}],"parameters":[{"name":"page","in":"query","required":false,"description":"Zero-based page index","schema":{"type":"integer","default":0}},{"name":"size","in":"query","required":false,"description":"Page size (max 100)","schema":{"type":"integer","default":20,"maximum":100}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/vendor/qr/single":{"post":{"tags":["Vendor"],"summary":"Creates a single QR record.","description":"Creates a single QR record. Auth: Vendor.","operationId":"postVendorQrSingle","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["vendorName","plantName"],"properties":{"customCode":{"type":"string","minLength":3,"maxLength":64},"vendorName":{"type":"string","maxLength":255},"vendorPhone":{"type":"string","maxLength":32},"vendorEmail":{"type":"string","format":"email"},"vendorAddress":{"type":"string","maxLength":1000},"vendorDistrict":{"type":"string","maxLength":100},"plantName":{"type":"string","maxLength":255},"species":{"type":"string","maxLength":255},"localName":{"type":"string","maxLength":255},"category":{"type":"string","default":"TREE"},"size":{"type":"string","default":"MEDIUM"},"description":{"type":"string","maxLength":2000},"metadata":{"type":"object","additionalProperties":true},"referencePhotos":{"type":"array","items":{"type":"string","format":"uri"},"maxItems":5}}}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/vendor/qr/batch":{"post":{"tags":["Vendor"],"summary":"Creates a batch QR record.","description":"Creates a batch QR record. Auth: Vendor.","operationId":"postVendorQrBatch","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["vendorName","batchName","plants"],"properties":{"customCode":{"type":"string","minLength":3,"maxLength":64},"vendorName":{"type":"string","maxLength":255},"vendorPhone":{"type":"string","maxLength":32},"vendorEmail":{"type":"string","format":"email"},"vendorAddress":{"type":"string","maxLength":1000},"vendorDistrict":{"type":"string","maxLength":100},"batchName":{"type":"string","maxLength":255},"plants":{"type":"array","minItems":1,"maxItems":500,"items":{"type":"object","required":["plantName"],"properties":{"plantName":{"type":"string","maxLength":255},"species":{"type":"string","maxLength":255},"localName":{"type":"string","maxLength":255},"category":{"type":"string","default":"TREE"},"size":{"type":"string","default":"MEDIUM"},"description":{"type":"string","maxLength":2000},"metadata":{"type":"object","additionalProperties":true},"referencePhotos":{"type":"array","items":{"type":"string","format":"uri"},"maxItems":5}}}}}}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/vendor/qr/{recordId}":{"delete":{"tags":["Vendor"],"summary":"Deletes or deactivates a vendor QR record.","description":"Deletes or deactivates a vendor QR record. Auth: Vendor.","operationId":"deleteVendorQrByRecordId","security":[{"bearerAuth":[]}],"parameters":[{"name":"recordId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/users/{userId}":{"get":{"tags":["Admin"],"summary":"Returns a user for admin review.","description":"Returns a user for admin review. Auth: Admin.","operationId":"getAdminUsersByUserId","security":[{"bearerAuth":[]}],"parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/users/{userId}/role":{"patch":{"tags":["Admin"],"summary":"Updates a user role.","description":"Updates a user role. Auth: Admin.","operationId":"patchAdminUsersByUserIdRole","security":[{"bearerAuth":[]}],"parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","required":["role"],"properties":{"role":{"type":"string","enum":["VENDOR","PLANTER","PUBLIC"]}}}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/verifications/flagged":{"get":{"tags":["Admin"],"summary":"Lists flagged planting verifications.","description":"Lists flagged planting verifications. Auth: Admin.","operationId":"getAdminVerificationsFlagged","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/verifications/{id}/approve":{"post":{"tags":["Admin"],"summary":"Approves a flagged planting verification.","description":"Approves a flagged planting verification. Auth: Admin.","operationId":"postAdminVerificationsByIdApprove","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"notes":{"type":"string"}}}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/verifications/{id}/reject":{"post":{"tags":["Admin"],"summary":"Rejects a flagged planting verification.","description":"Rejects a flagged planting verification. Auth: Admin.","operationId":"postAdminVerificationsByIdReject","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"notes":{"type":"string"}}}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/verifications/{id}/ai-review":{"post":{"tags":["Admin"],"summary":"Runs Gemini AI review for a planting and stores AI verification output.","description":"Runs Gemini AI review for a planting and stores AI verification output. Auth: Admin.","operationId":"postAdminVerificationsByIdAiReview","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/carbon/stats":{"get":{"tags":["Admin Carbon"],"summary":"Returns aggregate carbon statistics.","description":"Returns aggregate carbon statistics. Auth: Admin.","operationId":"getAdminCarbonStats","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/carbon/stats/district":{"get":{"tags":["Admin Carbon"],"summary":"Returns carbon statistics by district.","description":"Returns carbon statistics by district. Auth: Admin.","operationId":"getAdminCarbonStatsDistrict","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/carbon/stats/time":{"get":{"tags":["Admin Carbon"],"summary":"Returns carbon statistics by time period.","description":"Returns carbon statistics by time period. Auth: Admin.","operationId":"getAdminCarbonStatsTime","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/carbon/trends/monthly":{"get":{"tags":["Admin Carbon"],"summary":"Returns monthly carbon trends.","description":"Returns monthly carbon trends. Auth: Admin.","operationId":"getAdminCarbonTrendsMonthly","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/admin/carbon/leaderboard/districts":{"get":{"tags":["Admin Carbon"],"summary":"Returns district carbon leaderboard.","description":"Returns district carbon leaderboard. Auth: Admin.","operationId":"getAdminCarbonLeaderboardDistricts","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSuccess"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"ApiSuccess":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string"},"data":{"type":"object","additionalProperties":true},"timestamp":{"type":"string","format":"date-time"},"traceId":{"type":"string","format":"uuid"}},"required":["success","message","data","timestamp","traceId"]},"ApiError":{"type":"object","properties":{"success":{"type":"boolean","example":false},"message":{"type":"string"},"errorCode":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"traceId":{"type":"string","format":"uuid"}},"required":["success","message","errorCode","timestamp","traceId"]}}}}