openapi: 3.0.3 info: title: Qroplet Gateway API version: 1.0.0 description: | Combined OpenAPI document for the Kong gateway in Qroplet. Scope: - External gateway prefixes routed by Kong - Main business endpoints across management, agro, recommendation, remote sensing, alerts, and notification services - Internal endpoints that are reachable under `/api/*/internal/*` are documented for platform operators; they should remain network-restricted in production Notes: - Authentication is handled by Keycloak + Kong. - Downstream services rely on Kong-enriched headers such as `X-Tenant`, `X-User-Id`, and `X-Scopes`. - This spec is intentionally gateway-centric. Request/response schemas are summarized rather than exhaustively modeled per field. contact: name: Qroplet Backend servers: - url: http://localhost:8000 description: Local Kong proxy - url: https://api.qroplet.com description: Test gateway tags: - name: Gateway - name: Management - name: Agro - name: Recommendation - name: Feature Store - name: ML Models - name: Remote Sensing - name: Alerts - name: Notifications security: - BearerAuth: [] components: securitySchemes: BearerAuth: type: http scheme: bearer bearerFormat: JWT parameters: RequestId: name: X-Request-ID in: header required: false schema: type: string description: Optional correlation identifier. Kong can generate and echo this header. TenantHeader: name: X-Tenant in: header required: false schema: type: string description: Usually injected by Kong after auth/tenant resolution. ObjectId: name: object_id in: path required: true schema: type: string format: uuid ParcelId: name: parcel_id in: path required: true schema: type: string format: uuid TenantId: name: tenant_id in: path required: true schema: type: string schemas: ApiEnvelope: type: object properties: data: nullable: true error: $ref: '#/components/schemas/ErrorEnvelope' ErrorEnvelope: type: object properties: code: type: string message: type: string details: nullable: true GenericObject: type: object additionalProperties: true example: {} ListEnvelope: type: object properties: count: type: integer next: type: string nullable: true previous: type: string nullable: true results: type: array items: $ref: '#/components/schemas/GenericObject' example: count: 1 next: null previous: null results: - tenant_id: tnt_1 name: Example Resource status: active examples: TenantCreateExample: value: tenant_id: tnt_org_001 type: INDIVIDUAL owner_user_id: user-123 name: Demo Workspace domain: demo.example.com status: active country_code: TR timezone: UTC settings: {} InviteCreateExample: value: tenant_id: tnt_1 email: member@example.com role: tenant_user token_hash: token-1 expires_at: '2027-01-01T00:00:00Z' accepted_at: null created_by_user_id: owner-1 MemberCreateExample: value: tenant_id: tnt_1 user_id: member-1 email: member-1@example.com display_name: Member One role: tenant_user status: active invited_by_user_id: owner-1 UserProfileCreateExample: value: user_id: member-1 email: member-1@example.com display_name: Member One avatar_url: null locale: en timezone: UTC metadata: source: test RolePolicyCreateExample: value: role: field_agent scopes: - parcel:read SubscriptionCreateExample: value: tenant_id: tnt_1 plan: 11111111-1111-1111-1111-111111111111 status: active current_period_start: '2026-03-01T00:00:00Z' current_period_end: '2026-04-01T00:00:00Z' cancel_at_period_end: false canceled_at: null trial_end: null provider: stripe provider_customer_id: cus_123 provider_subscription_id: sub_123 ApiKeyCreateExample: value: name: integration-a metadata: env: prod created_by_user_id: user-123 ParcelCreateExample: value: name: Demo Wheat Parcel status: active address_text: Merkez, Sivas admin_area: country: TR province: Sivas district: Merkez cadastral_ref: country_code: TR city_code: '58' district_code: '001' block_no: '123' parcel_no: '45' created_by_user_id: demo ParcelVersionCreateExample: value: geometry: type: MultiPolygon coordinates: - - - - 40.731093 - 38.219193 - - 40.730896 - 38.235012 - - 40.725628 - 38.232525 - - 40.726213 - 38.220261 - - 40.731093 - 38.219193 valid_from: '2026-03-01T00:00:00Z' created_by_user_id: usr_demo ParcelSeasonCreateExample: value: parcel: 11111111-1111-1111-1111-111111111111 parcel_version: 22222222-2222-2222-2222-222222222222 season_year: 2026 season_label: 2026-main status: active created_by_user_id: usr_demo CropPlanCreateExample: value: parcel_season: 33333333-3333-3333-3333-333333333333 crop_id: wheat crop_name: Bread Wheat variety: Bezostaya planting_date: '2026-03-15' harvest_date_target: '2026-08-05' status: active notes: Trial parcel for phenology pipeline ParcelAcceptExample: value: parcel_version_id: 22222222-2222-2222-2222-222222222222 recommendation_id: 44444444-4444-4444-4444-444444444444 season_year: 2026 season_label: main crop_plan: crop_id: corn crop_name: Corn planting_date: '2026-03-01' harvest_date_target: '2026-09-01' status: active notes: spring season CadastralValidationExample: value: cadastral_ref: country_code: TR city_code: '06' district_code: '001' block_no: 12A parcel_no: '45' admin_area: country: TR GeoJsonImportExample: value: mode: create name: GeoJSON Imported Parcel status: active created_by_user_id: import-user geometry: type: Polygon coordinates: - - - 29.0 - 41.0 - - 29.0 - 41.02 - - 29.02 - 41.02 - - 29.02 - 41.0 - - 29.0 - 41.0 ClimateSnapshotIngestExample: value: parcel_id: 11111111-1111-1111-1111-111111111111 parcel_version_id: 22222222-2222-2222-2222-222222222222 lat: 39.92077 lon: 32.85411 years_back: 5 period_start: '2026-03-01' period_end: '2026-03-10' source: forecast_provider summary: tavg_c: 18.4 precip_mm: 22.1 meta: provider: open-meteo horizon_days: 10 PredictLocationExample: value: lat: 40.956974 lon: 40.612004 years_back: 5 top_n: 10 PredictLocationCropExample: value: lat: 36.830111 lon: 31.263075 years_back: 5 crop_slug: banana production_mode: greenhouse irrigation: false hybrid_alpha: 0.5 debug: true PredictPolygonExample: value: polygon: - - 40.731093 - 38.219193 - - 40.730896 - 38.235012 - - 40.725628 - 38.232525 - - 40.726213 - 38.220261 years_back: 5 top_candidates: 50 top_n: 5 grid_step_m: 500 max_points: 250 perennial_boost: 10 FeatureSetCreateExample: value: name: phenology_timeseries description: new schema revision schema: columns: - ndvi_mean_avg - evi_mean_avg owner_service: recommendation_service pipeline_git_sha: abc123 ObservationIngestExample: value: tenant_id: tnt_1 feature_set_name: qroplet_suitability feature_set_version: 1 soil: soil_ph: 6.5 organic_matter_pct: 2.1 climate: tavg_c: 18.4 precip_mm: 22.1 top: - crop_id: wheat slug: wheat score: 0.91 components: soil_score: 0.88 climate_modifier: 0.93 RSComputeExample: value: parcel_id: 11111111-1111-1111-1111-111111111111 parcel_version_id: 22222222-2222-2222-2222-222222222222 start_date: '2025-03-01' end_date: '2025-09-30' polygon_points: - - 40.731093 - 38.219193 - - 40.730896 - 38.235012 - - 40.725628 - 38.232525 - - 40.726213 - 38.220261 max_cloud: 30 limit: 50 include_assets: false min_valid_ratio: 0.6 max_cloud_ratio: 0.4 gap_fill_enabled: true gap_fill_max_gap_days: 20 smoothing_enabled: true smoothing_method: savitzky_golay smoothing_window: 5 smoothing_polyorder: 2 confidence_enabled: true phenology_enabled: true phenology_index: ndvi phenology_crop_type: wheat RSZoningRunExample: value: parcel_id: 11111111-1111-1111-1111-111111111111 parcel_version_id: 22222222-2222-2222-2222-222222222222 window_weeks: 12 AlertRuleCreateExample: value: name: Frost flowering rule type: FROST_RISK is_enabled: true config: warn_threshold: 0.55 critical_threshold: 0.78 weights: frost_risk: 0.6 temperature_deviation: 0.25 growth_deviation: 0.15 change_reason: initial rollout AlertEvaluateExample: value: alert_type: FROST_RISK phenology_phase: flowering frost_risk: 0.95 temperature_deviation: 0.8 growth_deviation: 0.25 warn_threshold: 0.55 critical_threshold: 0.78 NotificationEmitExample: value: user_id: user-1 type: ALERT title: Critical alert body: Irrigation required payload: parcel_id: p1 severity: CRITICAL status: unread delivered_channels: [] NotificationPreferenceExample: value: user_id: user-2 channels: push: true email: true min_severity: CRITICAL quiet_hours: {} RecommendationPersistExample: value: tenant_id: tnt_1 parcel_id: 11111111-1111-1111-1111-111111111111 parcel_version_id: 22222222-2222-2222-2222-222222222222 inputs_hash: abc123 model_name: crop_ranker model_version: '2' primary_crop_id: wheat primary_crop_name: wheat suitability_score: '0.99' explainability: top_result: why: soil: - good ph raw_output: results: - crop_id: wheat ScorecardCreateExample: value: parcel: 11111111-1111-1111-1111-111111111111 parcel_version: 22222222-2222-2222-2222-222222222222 recommendation: 33333333-3333-3333-3333-333333333333 soil_suitability_score: '85.00' climate_risk_score: '20.00' water_stress_score: '15.00' overall_risk_level: LOW explainability: run: 2 computed_at: '2026-02-12T00:00:00Z' EmptyObjectExample: value: {} MembershipResolveExample: value: tenant_id: tnt_1 user_id: member-1 TenantUpdateExample: value: tenant_id: tnt_1 type: INDIVIDUAL owner_user_id: owner-1 name: Tenant One Updated domain: one.example.com status: active country_code: TR timezone: UTC settings: {} MemberUpdateExample: value: tenant_id: tnt_1 user_id: member-1 email: member-1@example.com display_name: Member One role: tenant_admin status: active invited_by_user_id: owner-1 InviteUpdateExample: value: tenant_id: tnt_1 email: member@example.com role: tenant_user token_hash: token-2 expires_at: '2027-01-01T00:00:00Z' accepted_at: '2026-03-01T10:00:00Z' created_by_user_id: owner-1 UserProfileUpdateExample: value: user_id: member-1 email: member-1@example.com display_name: Member Prime avatar_url: null locale: tr timezone: Europe/Istanbul metadata: source: updated PlanCreateExample: value: code: pro_monthly name: Pro Monthly billing_period: monthly price_amount: '49.90' currency: USD features: weather_decadal_forecast: true api_access_management: true is_active: true SubscriptionUpdateExample: value: tenant_id: tnt_1 plan: 11111111-1111-1111-1111-111111111111 status: canceled current_period_start: '2026-03-01T00:00:00Z' current_period_end: '2026-04-01T00:00:00Z' cancel_at_period_end: false canceled_at: '2026-03-20T00:00:00Z' trial_end: null provider: stripe provider_customer_id: cus_123 provider_subscription_id: sub_123 InvoiceCreateExample: value: tenant_id: tnt_1 subscription: 11111111-1111-1111-1111-111111111111 amount_due: '49.90' amount_paid: '0.00' currency: USD status: open due_at: '2026-03-31T00:00:00Z' paid_at: null provider_invoice_id: inv_123 PaymentCreateExample: value: tenant_id: tnt_1 invoice: 11111111-1111-1111-1111-111111111111 amount: '49.90' currency: USD status: succeeded provider: stripe provider_payment_id: pay_123 method: card processed_at: '2026-03-15T12:00:00Z' AuditEventCreateExample: value: tenant_id: tnt_1 actor_user_id: owner-1 action: tenant.update target_type: tenant target_id: tnt_1 ip_address: 127.0.0.1 user_agent: swagger-ui metadata: source: manual ParcelUpdateExample: value: name: Archive Me status: archived address_text: null admin_area: {} cadastral_ref: {} created_by_user_id: user-1 ParcelVersionUpdateExample: value: valid_to: '2026-02-01T00:00:00Z' ParcelVersionRollbackExample: value: source_version_id: 22222222-2222-2222-2222-222222222222 created_by_user_id: user-1 valid_from: '2026-03-10T00:00:00Z' ParcelSeasonUpdateExample: value: parcel: 11111111-1111-1111-1111-111111111111 parcel_version: 22222222-2222-2222-2222-222222222222 season_year: 2026 season_label: main status: planned created_by_user_id: user-1 CropPlanUpdateExample: value: parcel_season: 33333333-3333-3333-3333-333333333333 crop_id: corn crop_name: Corn variety: Hybrid A planting_date: '2026-03-01' harvest_date_target: '2026-09-01' status: active notes: updated plan LearningFeedbackCreateExample: value: parcel: 11111111-1111-1111-1111-111111111111 parcel_version: 22222222-2222-2222-2222-222222222222 parcel_season: 33333333-3333-3333-3333-333333333333 crop_plan: 44444444-4444-4444-4444-444444444444 recommendation: 55555555-5555-5555-5555-555555555555 outcome_yield_kg_ha: '6200.00' satisfaction_score: 4 signals: pest_pressure: low notes: season performed as expected created_by_user_id: user-1 SoilSnapshotCreateExample: value: parcel: 11111111-1111-1111-1111-111111111111 parcel_version: 22222222-2222-2222-2222-222222222222 lat: 39.92077 lon: 32.85411 source: user_override smu_id: SMU-123 summary: soil_ph: 6.7 organic_matter_pct: 2.4 topsoil_0_30: clay_pct: 28 sand_pct: 34 computed_features: suitability_hint: medium captured_at: '2026-02-10T00:00:00Z' ClimateSnapshotCreateExample: value: parcel: 11111111-1111-1111-1111-111111111111 parcel_version: 22222222-2222-2222-2222-222222222222 lat: 39.92077 lon: 32.85411 years_back: 5 period_start: '2026-03-01' period_end: '2026-03-10' source: ERA5 summary: tavg_c: 18.4 precip_mm: 22.1 meta: provider: era5 captured_at: '2026-03-10T00:00:00Z' CropCatalogUpdateExample: value: crop_id: managed_corn slug: managed-corn scientific_name: Zea mays category: field_crop default_name_en: sweet corn names_i18n: en: sweet corn primary_regions: - TR - US synonyms: - maize thresholds: {} sources: {} is_active: true FeatureSetUpdateExample: value: name: phenology_timeseries version: 2 description: updated schema revision schema: columns: - ndvi_mean_avg - evi_mean_avg - los_days is_active: false owner_service: recommendation_service pipeline_git_sha: def456 ExportCreateExample: value: feature_set: 1 name: qroplet_suitability_train_2026_03 filters: tenant_id: tnt_1 date_from: '2026-01-01' date_to: '2026-03-01' row_count: 1245 storage_uri: s3://qroplet-exports/train-2026-03.parquet checksum: sha256:abc123 created_by_user_id: user-1 MLModelCreateExample: value: name: global_ranker model_type: lgbm_ranker feature_set: 1 artifact_uri: artifacts/global_ranker.pkl status: staging signature: features: - soil_ph metrics: ndcg: 0.91 MLModelUpdateExample: value: name: global_ranker model_type: lgbm_ranker feature_set: 1 artifact_uri: artifacts/global_ranker.pkl status: production signature: features: - soil_ph metrics: ndcg: 0.94 PredictGenericExample: value: lat: 40.956974 lon: 40.612004 years_back: 5 top_n: 5 PhenologyPredictExample: value: parcel_id: 11111111-1111-1111-1111-111111111111 crop_slug: wheat planting_date: '2026-03-01' season_year: 2026 NdviSnapshotCreateExample: value: parcel_id: 11111111-1111-1111-1111-111111111111 parcel_version_id: 22222222-2222-2222-2222-222222222222 observed_week_start: '2026-01-01' observed_week_end: '2026-01-07' ndvi_mean: 0.4 ndvi_p10: 0.31 ndvi_p90: 0.52 evi_mean: 0.28 evi_p10: 0.2 evi_p90: 0.36 quality_flags: valid_pixel_ratio: 0.93 source: provider raw: {} VegetationBaselineCreateExample: value: parcel_id: 11111111-1111-1111-1111-111111111111 parcel_version_id: 22222222-2222-2222-2222-222222222222 method: rolling_mean baseline: mean: 0.42 p10: 0.31 p90: 0.55 AnomalyCreateExample: value: parcel_id: 11111111-1111-1111-1111-111111111111 observed_week_start: '2026-01-01' anomaly_score: '0.31' severity: CRITICAL deviation: delta: 0.31 baseline: mean: 0.12 AlertCreateExample: value: parcel_id: 11111111-1111-1111-1111-111111111111 parcel_season_id: 33333333-3333-3333-3333-333333333333 type: WATER_STRESS_RISK severity: WARN confidence: '0.700' window_start: '2026-01-01T00:00:00Z' window_end: '2026-01-07T00:00:00Z' recommended_action: {} evidence: {} causal_analysis: {} status: open AlertRuleRollbackExample: value: version: 1 reason: rollback test RetentionPurgeExample: value: dry_run: true batch_size: 10 ScheduledEvaluateExample: value: parcel_ids: - 11111111-1111-1111-1111-111111111111 alert_type: WATER_STRESS_RISK NotificationCreateExample: value: user_id: user-1 type: ALERT title: Critical alert body: Irrigation required payload: parcel_id: p1 severity: CRITICAL status: unread delivered_channels: [] NotificationUpdateExample: value: user_id: user-1 type: ALERT title: Critical alert body: Irrigation required payload: parcel_id: p1 severity: CRITICAL status: read delivered_channels: - push DeliveryAttemptCreateExample: value: notification: 11111111-1111-1111-1111-111111111111 channel: email status: pending attempt_no: 1 provider_response: {} responses: Ok: description: Successful response content: application/json: schema: $ref: '#/components/schemas/ApiEnvelope' Created: description: Created response content: application/json: schema: $ref: '#/components/schemas/ApiEnvelope' Accepted: description: Accepted response content: application/json: schema: $ref: '#/components/schemas/ApiEnvelope' ValidationError: description: Validation or semantic error content: application/json: schema: type: object properties: error: $ref: '#/components/schemas/ErrorEnvelope' Unauthorized: description: Missing or invalid authentication Forbidden: description: Insufficient scope or role NotFound: description: Resource not found paths: /health: get: tags: [Gateway] summary: Public gateway health route security: [] parameters: - $ref: '#/components/parameters/RequestId' responses: '200': description: Gateway upstream health payload /metrics: get: tags: [Gateway] summary: Public metrics endpoint security: [] responses: '200': description: Prometheus text payload /api/management/tenants/: get: tags: [Management] summary: List tenants parameters: - $ref: '#/components/parameters/RequestId' responses: '200': $ref: '#/components/responses/Ok' post: tags: [Management] summary: Create tenant requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/TenantCreateExample' responses: '201': $ref: '#/components/responses/Created' /api/management/tenants/{object_id}: get: tags: [Management] summary: Get tenant detail parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' put: tags: [Management] summary: Update tenant parameters: - $ref: '#/components/parameters/ObjectId' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/TenantUpdateExample' responses: '200': $ref: '#/components/responses/Ok' /api/management/organizations/: get: tags: [Management] summary: List organizations responses: '200': $ref: '#/components/responses/Ok' post: tags: [Management] summary: Create organization requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/GenericObject' responses: '201': $ref: '#/components/responses/Created' /api/management/organizations/{object_id}: get: tags: [Management] summary: Get organization detail parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' put: tags: [Management] summary: Update organization parameters: - $ref: '#/components/parameters/ObjectId' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/GenericObject' responses: '200': $ref: '#/components/responses/Ok' delete: tags: [Management] summary: Delete organization parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' /api/management/members/: get: tags: [Management] summary: List tenant members responses: '200': $ref: '#/components/responses/Ok' post: tags: [Management] summary: Create tenant membership requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/MemberCreateExample' responses: '201': $ref: '#/components/responses/Created' /api/management/members/{object_id}: get: tags: [Management] summary: Get membership detail parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' put: tags: [Management] summary: Update membership or role parameters: - $ref: '#/components/parameters/ObjectId' requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/MemberUpdateExample' responses: '200': $ref: '#/components/responses/Ok' /api/management/organization-members/: get: tags: [Management] summary: List organization members responses: '200': $ref: '#/components/responses/Ok' post: tags: [Management] summary: Create organization membership requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/GenericObject' responses: '201': $ref: '#/components/responses/Created' /api/management/organization-members/{object_id}: get: tags: [Management] summary: Get organization membership detail parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' put: tags: [Management] summary: Update organization membership parameters: - $ref: '#/components/parameters/ObjectId' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/GenericObject' responses: '200': $ref: '#/components/responses/Ok' delete: tags: [Management] summary: Delete organization membership parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' /api/management/invites/: get: tags: [Management] summary: List invites responses: '200': $ref: '#/components/responses/Ok' post: tags: [Management] summary: Create invite requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/InviteCreateExample' responses: '201': $ref: '#/components/responses/Created' /api/management/invites/{object_id}: get: tags: [Management] summary: Get invite detail parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' put: tags: [Management] summary: Update invite state parameters: - $ref: '#/components/parameters/ObjectId' requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/InviteUpdateExample' responses: '200': $ref: '#/components/responses/Ok' /api/management/role-policies/: get: tags: [Management] summary: List role policies responses: '200': $ref: '#/components/responses/Ok' post: tags: [Management] summary: Create role policy requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/RolePolicyCreateExample' responses: '201': $ref: '#/components/responses/Created' /api/management/role-policies/{object_id}: get: tags: [Management] summary: Get role policy parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' put: tags: [Management] summary: Update role policy parameters: - $ref: '#/components/parameters/ObjectId' requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/RolePolicyCreateExample' responses: '200': $ref: '#/components/responses/Ok' /api/management/plans/: get: tags: [Management] summary: List plans responses: '200': $ref: '#/components/responses/Ok' post: tags: [Management] summary: Create plan requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/PlanCreateExample' responses: '201': $ref: '#/components/responses/Created' /api/management/plans/{object_id}: get: tags: [Management] summary: Get plan detail parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' put: tags: [Management] summary: Update plan parameters: - $ref: '#/components/parameters/ObjectId' requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/PlanCreateExample' responses: '200': $ref: '#/components/responses/Ok' /api/management/subscriptions/: get: tags: [Management] summary: List subscriptions responses: '200': $ref: '#/components/responses/Ok' post: tags: [Management] summary: Create or upgrade subscription requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/SubscriptionCreateExample' responses: '201': $ref: '#/components/responses/Created' /api/management/subscriptions/{object_id}: get: tags: [Management] summary: Get subscription detail parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' put: tags: [Management] summary: Update subscription parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/SubscriptionUpdateExample' /api/management/invoices/: get: tags: [Management] summary: List invoices responses: '200': $ref: '#/components/responses/Ok' post: tags: [Management] summary: Create invoice requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/InvoiceCreateExample' responses: '201': $ref: '#/components/responses/Created' /api/management/invoices/{object_id}: get: tags: [Management] summary: Get invoice detail parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' /api/management/payments/: get: tags: [Management] summary: List payments responses: '200': $ref: '#/components/responses/Ok' post: tags: [Management] summary: Create payment requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/PaymentCreateExample' responses: '201': $ref: '#/components/responses/Created' /api/management/payments/{object_id}: get: tags: [Management] summary: Get payment detail parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' /api/management/user-profiles/: get: tags: [Management] summary: List user profiles responses: '200': $ref: '#/components/responses/Ok' post: tags: [Management] summary: Create user profile requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/UserProfileCreateExample' responses: '201': $ref: '#/components/responses/Created' /api/management/user-profiles/{object_id}: get: tags: [Management] summary: Get user profile parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' put: tags: [Management] summary: Update user profile parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/UserProfileUpdateExample' /api/management/api-keys/: get: tags: [Management] summary: List API keys responses: '200': $ref: '#/components/responses/Ok' post: tags: [Management] summary: Create API key requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/ApiKeyCreateExample' responses: '201': $ref: '#/components/responses/Created' /api/management/api-keys/{object_id}/rotate: post: tags: [Management] summary: Rotate API key parameters: - $ref: '#/components/parameters/ObjectId' requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/EmptyObjectExample' responses: '200': $ref: '#/components/responses/Ok' /api/management/api-keys/{object_id}/revoke: post: tags: [Management] summary: Revoke API key parameters: - $ref: '#/components/parameters/ObjectId' requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/EmptyObjectExample' responses: '200': $ref: '#/components/responses/Ok' /api/management/audit-events/: get: tags: [Management] summary: List audit events responses: '200': $ref: '#/components/responses/Ok' post: tags: [Management] summary: Create audit event requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/AuditEventCreateExample' responses: '201': $ref: '#/components/responses/Created' /api/management/audit-events/{object_id}: get: tags: [Management] summary: Get audit event parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' /api/management/internal/membership/resolve: post: tags: [Management] summary: Resolve internal membership context description: Internal operator or service endpoint. requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/MembershipResolveExample' responses: '200': $ref: '#/components/responses/Ok' /api/management/internal/organization-access/resolve: get: tags: [Management] summary: Resolve internal organization access description: Internal operator or service endpoint. responses: '200': $ref: '#/components/responses/Ok' /api/management/internal/context/bootstrap: get: tags: [Management] summary: Get internal bootstrap context description: Internal user, tenant, and organization bootstrap endpoint. responses: '200': $ref: '#/components/responses/Ok' /api/management/internal/tenant-features/{tenant_id}: get: tags: [Management] summary: Get tenant features description: Internal feature/plan resolution endpoint. parameters: - $ref: '#/components/parameters/TenantId' responses: '200': $ref: '#/components/responses/Ok' /api/management/user/work-summary: get: tags: [Management] summary: Get user work summary dashboard counters responses: '200': $ref: '#/components/responses/Ok' /api/agro/parcels/: get: tags: [Agro] summary: List parcels responses: '200': $ref: '#/components/responses/Ok' post: tags: [Agro] summary: Create parcel requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/ParcelCreateExample' responses: '201': $ref: '#/components/responses/Created' /api/agro/parcels/validate-cadastral-ref: post: tags: [Agro] summary: Validate cadastral reference requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/CadastralValidationExample' responses: '200': $ref: '#/components/responses/Ok' /api/agro/parcels/{object_id}: get: tags: [Agro] summary: Get parcel detail parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' put: tags: [Agro] summary: Update or archive parcel parameters: - $ref: '#/components/parameters/ObjectId' requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/ParcelUpdateExample' responses: '200': $ref: '#/components/responses/Ok' delete: tags: [Agro] summary: Soft-delete parcel parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' /api/agro/parcels/{parcel_id}/versions/: post: tags: [Agro] summary: Create parcel version parameters: - $ref: '#/components/parameters/ParcelId' requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/ParcelVersionCreateExample' responses: '201': $ref: '#/components/responses/Created' /api/agro/parcels/import/geojson: post: tags: [Agro] summary: Import parcel from GeoJSON requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/GeoJsonImportExample' responses: '200': $ref: '#/components/responses/Ok' /api/agro/parcels/{parcel_id}/versions/diff: get: tags: [Agro] summary: Diff parcel versions parameters: - $ref: '#/components/parameters/ParcelId' responses: '200': $ref: '#/components/responses/Ok' /api/agro/parcels/{parcel_id}/versions/rollback: post: tags: [Agro] summary: Roll back parcel version parameters: - $ref: '#/components/parameters/ParcelId' requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/ParcelVersionRollbackExample' responses: '201': $ref: '#/components/responses/Created' /api/agro/parcels/{parcel_id}/accept: post: tags: [Agro] summary: Accept recommendation and start season parameters: - $ref: '#/components/parameters/ParcelId' requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/ParcelAcceptExample' responses: '200': $ref: '#/components/responses/Ok' /api/agro/parcels/{parcel_id}/recommendations: get: tags: [Agro] summary: List parcel recommendation history parameters: - $ref: '#/components/parameters/ParcelId' responses: '200': $ref: '#/components/responses/Ok' /api/agro/parcels/{parcel_id}/scorecard: get: tags: [Agro] summary: Get latest parcel scorecard parameters: - $ref: '#/components/parameters/ParcelId' responses: '200': $ref: '#/components/responses/Ok' /api/agro/parcels/bulk-scorecards: get: tags: [Agro] summary: List latest parcel scorecards in bulk parameters: - name: organization_id in: query required: false schema: type: string - name: parcel_ids in: query required: false schema: type: string description: Comma-separated parcel UUID list. responses: '200': $ref: '#/components/responses/Ok' /api/agro/parcels/{parcel_id}/scorecard/recompute: post: tags: [Agro] summary: Recompute parcel scorecard parameters: - $ref: '#/components/parameters/ParcelId' requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/EmptyObjectExample' responses: '201': $ref: '#/components/responses/Created' /api/agro/parcels/{parcel_id}/zones: get: tags: [Agro] summary: List parcel zones parameters: - $ref: '#/components/parameters/ParcelId' responses: '200': $ref: '#/components/responses/Ok' /api/agro/parcels/{parcel_id}/weather/decadal: get: tags: [Agro] summary: Get decadal weather forecast for parcel parameters: - $ref: '#/components/parameters/ParcelId' responses: '200': $ref: '#/components/responses/Ok' /api/agro/parcels/{parcel_id}/weather/current: get: tags: [Agro] summary: Get current weather snapshot for parcel parameters: - $ref: '#/components/parameters/ParcelId' responses: '200': $ref: '#/components/responses/Ok' /api/agro/parcels/{parcel_id}/weather/10day: get: tags: [Agro] summary: Get 10-day weather forecast for parcel parameters: - $ref: '#/components/parameters/ParcelId' responses: '200': $ref: '#/components/responses/Ok' /api/agro/parcels/{parcel_id}/weather/historical: get: tags: [Agro] summary: Get historical daily weather series for parcel parameters: - $ref: '#/components/parameters/ParcelId' - name: days in: query required: false schema: type: integer minimum: 1 maximum: 90 responses: '200': $ref: '#/components/responses/Ok' /api/agro/weather/decadal: get: tags: [Agro] summary: Get decadal weather forecast by parcel query parameter parameters: - name: parcel_id in: query required: true schema: type: string format: uuid - name: horizon_days in: query required: false schema: type: integer minimum: 10 maximum: 30 responses: '200': $ref: '#/components/responses/Ok' /api/agro/weather/current: get: tags: [Agro] summary: Get current weather snapshot by parcel query parameter parameters: - name: parcel_id in: query required: true schema: type: string format: uuid responses: '200': $ref: '#/components/responses/Ok' /api/agro/weather/10day: get: tags: [Agro] summary: Get 10-day weather forecast by parcel query parameter parameters: - name: parcel_id in: query required: true schema: type: string format: uuid responses: '200': $ref: '#/components/responses/Ok' /api/agro/weather/historical: get: tags: [Agro] summary: Get historical daily weather series by parcel query parameter parameters: - name: parcel_id in: query required: true schema: type: string format: uuid - name: days in: query required: false schema: type: integer minimum: 1 maximum: 90 responses: '200': $ref: '#/components/responses/Ok' /api/agro/season-timeline: get: tags: [Agro] summary: List active and planned parcel seasons with crop timeline parameters: - name: organization_id in: query required: true schema: type: string - name: season_year in: query required: false schema: type: integer responses: '200': $ref: '#/components/responses/Ok' /api/learning/feedback/: get: tags: [Agro] summary: List parcel learning feedback responses: '200': $ref: '#/components/responses/Ok' post: tags: [Agro] summary: Create parcel learning feedback requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/LearningFeedbackCreateExample' responses: '201': $ref: '#/components/responses/Created' /api/agro/parcel-versions/: get: tags: [Agro] summary: List parcel versions responses: '200': $ref: '#/components/responses/Ok' /api/agro/parcel-versions/{object_id}: get: tags: [Agro] summary: Get parcel version parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' put: tags: [Agro] summary: Update allowed parcel version fields parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/ParcelVersionUpdateExample' /api/agro/parcel-seasons/: get: tags: [Agro] summary: List parcel seasons responses: '200': $ref: '#/components/responses/Ok' post: tags: [Agro] summary: Create parcel season requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/ParcelSeasonCreateExample' responses: '201': $ref: '#/components/responses/Created' /api/agro/parcel-seasons/{object_id}: get: tags: [Agro] summary: Get parcel season parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' put: tags: [Agro] summary: Update parcel season parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/ParcelSeasonUpdateExample' /api/agro/internal/parcels/{parcel_id}/seasons/{season_year}/: get: tags: [Agro] summary: Get parcel season date range for internal consumers parameters: - $ref: '#/components/parameters/ParcelId' - name: season_year in: path required: true schema: type: integer responses: '200': $ref: '#/components/responses/Ok' /api/agro/crop-plans/: get: tags: [Agro] summary: List crop plans responses: '200': $ref: '#/components/responses/Ok' post: tags: [Agro] summary: Create crop plan requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/CropPlanCreateExample' responses: '201': $ref: '#/components/responses/Created' /api/agro/crop-plans/{object_id}: get: tags: [Agro] summary: Get crop plan parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' put: tags: [Agro] summary: Update crop plan parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/CropPlanUpdateExample' /api/agro/soil-snapshots/: get: tags: [Agro] summary: List soil snapshots responses: '200': $ref: '#/components/responses/Ok' post: tags: [Agro] summary: Create soil snapshot requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/SoilSnapshotCreateExample' responses: '201': $ref: '#/components/responses/Created' /api/agro/soil-snapshots/{object_id}: get: tags: [Agro] summary: Get soil snapshot parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' /api/agro/climate-snapshots/: get: tags: [Agro] summary: List climate snapshots responses: '200': $ref: '#/components/responses/Ok' post: tags: [Agro] summary: Create climate snapshot requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/ClimateSnapshotCreateExample' responses: '201': $ref: '#/components/responses/Created' /api/agro/climate-snapshots/{object_id}: get: tags: [Agro] summary: Get climate snapshot parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' /api/agro/internal/climate-snapshots/ingest: post: tags: [Agro] summary: Ingest climate snapshot internally description: Internal ingestion endpoint used by scheduled provider jobs. requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/ClimateSnapshotIngestExample' responses: '200': $ref: '#/components/responses/Ok' '201': $ref: '#/components/responses/Created' /api/agro/recommendations/: get: tags: [Agro] summary: List persisted parcel recommendations responses: '200': $ref: '#/components/responses/Ok' post: tags: [Agro] summary: Persist recommendation result requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/RecommendationPersistExample' responses: '200': $ref: '#/components/responses/Ok' '201': $ref: '#/components/responses/Created' /api/agro/recommendations/{object_id}: get: tags: [Agro] summary: Get persisted recommendation parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' /api/agro/scorecards/: get: tags: [Agro] summary: List scorecards responses: '200': $ref: '#/components/responses/Ok' post: tags: [Agro] summary: Create scorecard requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/ScorecardCreateExample' responses: '200': $ref: '#/components/responses/Ok' '201': $ref: '#/components/responses/Created' /api/agro/scorecards/{object_id}: get: tags: [Agro] summary: Get scorecard detail parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' /api/agro/zones/: get: tags: [Agro] summary: List agro parcel zones responses: '200': $ref: '#/components/responses/Ok' /api/agro/zones/{object_id}: get: tags: [Agro] summary: Get agro zone detail parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' /api/agro/crops/: get: tags: [Agro] summary: List crop catalog responses: '200': $ref: '#/components/responses/Ok' post: tags: [Agro] summary: Create crop catalog item requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/CropCatalogUpdateExample' responses: '201': $ref: '#/components/responses/Created' /api/agro/crops/{object_id}: get: tags: [Agro] summary: Get crop catalog item parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' put: tags: [Agro] summary: Update crop catalog item parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/CropCatalogUpdateExample' /api/feature-store/health/: get: tags: [Feature Store] summary: Feature store health responses: '200': $ref: '#/components/responses/Ok' /api/feature-store/health/snapshots/latest/: get: tags: [Feature Store] summary: Latest feature store health snapshot responses: '200': $ref: '#/components/responses/Ok' /api/feature-store/feature-sets/: get: tags: [Feature Store] summary: List feature sets responses: '200': $ref: '#/components/responses/Ok' post: tags: [Feature Store] summary: Create feature set requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/FeatureSetCreateExample' responses: '201': $ref: '#/components/responses/Created' /api/feature-store/feature-sets/{object_id}: get: tags: [Feature Store] summary: Get feature set parameters: - name: object_id in: path required: true schema: type: integer responses: '200': $ref: '#/components/responses/Ok' put: tags: [Feature Store] summary: Update feature set parameters: - name: object_id in: path required: true schema: type: integer requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/FeatureSetUpdateExample' responses: '200': $ref: '#/components/responses/Ok' delete: tags: [Feature Store] summary: Delete feature set parameters: - name: object_id in: path required: true schema: type: integer responses: '200': $ref: '#/components/responses/Ok' /api/feature-store/feature-sets/{object_id}/activate: post: tags: [Feature Store] summary: Activate feature set version parameters: - name: object_id in: path required: true schema: type: integer requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/EmptyObjectExample' responses: '200': $ref: '#/components/responses/Ok' /api/feature-store/observations/: get: tags: [Feature Store] summary: List observations responses: '200': $ref: '#/components/responses/Ok' post: tags: [Feature Store] summary: Create observation requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/ObservationIngestExample' responses: '201': $ref: '#/components/responses/Created' /api/feature-store/observations/{object_id}: get: tags: [Feature Store] summary: Get observation detail parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' /api/feature-store/exports/: get: tags: [Feature Store] summary: List rank dataset exports responses: '200': $ref: '#/components/responses/Ok' post: tags: [Feature Store] summary: Create rank dataset export requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/ExportCreateExample' responses: '201': $ref: '#/components/responses/Created' /api/feature-store/exports/{object_id}: get: tags: [Feature Store] summary: Get rank dataset export parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' /api/ml-models/: get: tags: [ML Models] summary: List ML models responses: '200': $ref: '#/components/responses/Ok' post: tags: [ML Models] summary: Register ML model requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/MLModelCreateExample' responses: '201': $ref: '#/components/responses/Created' /api/ml-models/active/: get: tags: [ML Models] summary: Get active ML model responses: '200': $ref: '#/components/responses/Ok' /api/ml-models/{object_id}: get: tags: [ML Models] summary: Get ML model detail parameters: - name: object_id in: path required: true schema: type: integer responses: '200': $ref: '#/components/responses/Ok' put: tags: [ML Models] summary: Update ML model parameters: - name: object_id in: path required: true schema: type: integer requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/MLModelUpdateExample' responses: '200': $ref: '#/components/responses/Ok' /api/feature-store/predict/: post: tags: [Recommendation] summary: Run rerank inference requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/PredictGenericExample' responses: '200': $ref: '#/components/responses/Ok' /api/feature-store/predict/phenology: post: tags: [Recommendation] summary: Predict phenology requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/PhenologyPredictExample' responses: '200': $ref: '#/components/responses/Ok' /api/feature-store/predict/location/: post: tags: [Recommendation] summary: Predict recommendations by location requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/PredictLocationExample' responses: '200': $ref: '#/components/responses/Ok' /api/feature-store/predict/location/polygon/: post: tags: [Recommendation] summary: Predict recommendations by polygon requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/PredictPolygonExample' responses: '200': $ref: '#/components/responses/Ok' /api/recommend/ingest/: post: tags: [Feature Store] summary: Ingest flattened observation payload requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/ObservationIngestExample' responses: '200': $ref: '#/components/responses/Ok' '201': $ref: '#/components/responses/Created' /api/recommend/dataset/: get: tags: [Feature Store] summary: Export dataset responses: '200': description: CSV or JSONL export stream /api/recommend/predict/location/: post: tags: [Recommendation] summary: Public location recommendation endpoint requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/PredictLocationExample' responses: '200': $ref: '#/components/responses/Ok' /api/recommend/internal/water-signal/: post: tags: [Recommendation] summary: Internal WaPOR-based water signal endpoint requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' responses: '200': $ref: '#/components/responses/Ok' /api/recommend/predict/location/crop/: post: tags: [Recommendation] summary: Public single-crop location endpoint requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/PredictLocationCropExample' responses: '200': $ref: '#/components/responses/Ok' /api/recommend/predict/location/polygon/: post: tags: [Recommendation] summary: Public polygon recommendation endpoint requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/PredictPolygonExample' responses: '200': $ref: '#/components/responses/Ok' /api/recommend/predict/: post: tags: [Recommendation] summary: Public rerank inference endpoint requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/PredictGenericExample' responses: '200': $ref: '#/components/responses/Ok' /api/recommend/recommendations/{object_id}/crop-scores: get: tags: [Recommendation] summary: Get recommendation crop score decomposition parameters: - name: object_id in: path required: true schema: type: integer - name: crop_id in: query required: false schema: type: string - name: slug in: query required: false schema: type: string responses: '200': $ref: '#/components/responses/Ok' /api/rs/ndvi-snapshots/: get: tags: [Remote Sensing] summary: List NDVI snapshots responses: '200': $ref: '#/components/responses/Ok' post: tags: [Remote Sensing] summary: Create NDVI snapshot requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/NdviSnapshotCreateExample' responses: '201': $ref: '#/components/responses/Created' /api/rs/ndvi-snapshots/{object_id}: get: tags: [Remote Sensing] summary: Get NDVI snapshot parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' put: tags: [Remote Sensing] summary: Update NDVI snapshot parameters: - $ref: '#/components/parameters/ObjectId' requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' responses: '200': $ref: '#/components/responses/Ok' delete: tags: [Remote Sensing] summary: Delete NDVI snapshot parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' /api/rs/vegetation-baselines/: get: tags: [Remote Sensing] summary: List vegetation baselines responses: '200': $ref: '#/components/responses/Ok' post: tags: [Remote Sensing] summary: Create vegetation baseline requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/VegetationBaselineCreateExample' responses: '201': $ref: '#/components/responses/Created' /api/rs/vegetation-baselines/{object_id}: get: tags: [Remote Sensing] summary: Get vegetation baseline parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' put: tags: [Remote Sensing] summary: Update vegetation baseline parameters: - $ref: '#/components/parameters/ObjectId' requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' responses: '200': $ref: '#/components/responses/Ok' delete: tags: [Remote Sensing] summary: Delete vegetation baseline parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' /api/rs/parcels/{parcel_id}/vegetation-baseline: get: tags: [Remote Sensing] summary: Get parcel vegetation baseline with season context parameters: - $ref: '#/components/parameters/ParcelId' - name: season_year in: query required: true schema: type: integer - name: parcel_version_id in: query required: false schema: type: string format: uuid responses: '200': $ref: '#/components/responses/Ok' /api/rs/parcels/bulk-monitoring-summary: get: tags: [Remote Sensing] summary: List latest monitoring summary rows for organization parcels parameters: - name: organization_id in: query required: true schema: type: string responses: '200': $ref: '#/components/responses/Ok' /api/rs/anomalies/: get: tags: [Remote Sensing] summary: List anomaly results responses: '200': $ref: '#/components/responses/Ok' post: tags: [Remote Sensing] summary: Create anomaly result requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/AnomalyCreateExample' responses: '201': $ref: '#/components/responses/Created' /api/rs/anomalies/{object_id}: get: tags: [Remote Sensing] summary: Get anomaly result parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' put: tags: [Remote Sensing] summary: Update anomaly result parameters: - $ref: '#/components/parameters/ObjectId' requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' responses: '200': $ref: '#/components/responses/Ok' delete: tags: [Remote Sensing] summary: Delete anomaly result parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' /api/rs/water-stress/: get: tags: [Remote Sensing] summary: List water stress snapshots responses: '200': $ref: '#/components/responses/Ok' post: tags: [Remote Sensing] summary: Create water stress snapshot requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' responses: '201': $ref: '#/components/responses/Created' /api/rs/water-stress/{object_id}: get: tags: [Remote Sensing] summary: Get water stress snapshot parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' put: tags: [Remote Sensing] summary: Update water stress snapshot parameters: - $ref: '#/components/parameters/ObjectId' requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' responses: '200': $ref: '#/components/responses/Ok' delete: tags: [Remote Sensing] summary: Delete water stress snapshot parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' /api/rs/zones/: get: tags: [Remote Sensing] summary: List remote sensing zones responses: '200': $ref: '#/components/responses/Ok' post: tags: [Remote Sensing] summary: Create remote sensing zone requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' responses: '201': $ref: '#/components/responses/Created' /api/rs/zones/{object_id}: get: tags: [Remote Sensing] summary: Get remote sensing zone parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' put: tags: [Remote Sensing] summary: Update remote sensing zone parameters: - $ref: '#/components/parameters/ObjectId' requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' responses: '200': $ref: '#/components/responses/Ok' delete: tags: [Remote Sensing] summary: Delete remote sensing zone parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' /api/rs/parcels/{parcel_id}/ndvi: get: tags: [Remote Sensing] summary: Get parcel NDVI time series parameters: - $ref: '#/components/parameters/ParcelId' responses: '200': $ref: '#/components/responses/Ok' /api/rs/parcels/{parcel_id}/anomalies: get: tags: [Remote Sensing] summary: Get parcel anomalies parameters: - $ref: '#/components/parameters/ParcelId' responses: '200': $ref: '#/components/responses/Ok' /api/rs/parcels/{parcel_id}/water-stress: get: tags: [Remote Sensing] summary: Get parcel water stress history parameters: - $ref: '#/components/parameters/ParcelId' responses: '200': $ref: '#/components/responses/Ok' /api/rs/parcels/{parcel_id}/soil-moisture: get: tags: [Remote Sensing] summary: Get parcel soil moisture history parameters: - $ref: '#/components/parameters/ParcelId' responses: '200': $ref: '#/components/responses/Ok' /api/rs/parcels/{parcel_id}/soil-moisture/latest: get: tags: [Remote Sensing] summary: Get latest parcel soil moisture snapshot parameters: - $ref: '#/components/parameters/ParcelId' responses: '200': $ref: '#/components/responses/Ok' '404': $ref: '#/components/responses/Error' /api/rs/parcels/{parcel_id}/irrigation-pressure: get: tags: [Remote Sensing] summary: Get parcel irrigation pressure history parameters: - $ref: '#/components/parameters/ParcelId' responses: '200': $ref: '#/components/responses/Ok' /api/rs/parcels/{parcel_id}/irrigation-pressure/latest: get: tags: [Remote Sensing] summary: Get latest parcel irrigation pressure snapshot parameters: - $ref: '#/components/parameters/ParcelId' responses: '200': $ref: '#/components/responses/Ok' '404': $ref: '#/components/responses/Error' /api/rs/parcels/{parcel_id}/monitoring-summary: get: tags: [Remote Sensing] summary: Get parcel monitoring summary parameters: - $ref: '#/components/parameters/ParcelId' responses: '200': $ref: '#/components/responses/Ok' /api/rs/parcels/{parcel_id}/runs: get: tags: [Remote Sensing] summary: Get recent parcel remote sensing runs parameters: - $ref: '#/components/parameters/ParcelId' responses: '200': $ref: '#/components/responses/Ok' /api/rs/parcels/{parcel_id}/phenology/latest: get: tags: [Remote Sensing] summary: Get latest parcel phenology parameters: - $ref: '#/components/parameters/ParcelId' responses: '200': $ref: '#/components/responses/Ok' /api/rs/parcels/{parcel_id}/phenology/history: get: tags: [Remote Sensing] summary: Get parcel phenology history parameters: - $ref: '#/components/parameters/ParcelId' responses: '200': $ref: '#/components/responses/Ok' /api/rs/parcels/{parcel_id}/phenology/status: get: tags: [Remote Sensing] summary: Get parcel phenology run status parameters: - $ref: '#/components/parameters/ParcelId' responses: '200': $ref: '#/components/responses/Ok' /api/rs/parcels/{parcel_id}/yield-forecast: get: tags: [Remote Sensing] summary: Get parcel yield forecast parameters: - $ref: '#/components/parameters/ParcelId' responses: '200': $ref: '#/components/responses/Ok' /api/rs/internal/run/weekly: post: tags: [Remote Sensing] summary: Trigger weekly run description: Internal scheduled endpoint. responses: '202': $ref: '#/components/responses/Accepted' /api/rs/internal/run/phenology-projection: post: tags: [Remote Sensing] summary: Create current-season phenology projection from historical records requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: value: parcel_id: "11111111-1111-1111-1111-111111111111" parcel_version_id: "22222222-2222-2222-2222-222222222222" crop_slug: "wheat" planting_date: "2024-11-01" season_year: 2025 history_years: 3 responses: '201': $ref: '#/components/responses/Created' '400': $ref: '#/components/responses/BadRequest' '404': $ref: '#/components/responses/NotFound' /api/rs/internal/run/zoning: post: tags: [Remote Sensing] summary: Trigger zoning run requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/RSZoningRunExample' responses: '202': $ref: '#/components/responses/Accepted' /api/rs/internal/run/water-stress: post: tags: [Remote Sensing] summary: Trigger water stress run requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' responses: '202': $ref: '#/components/responses/Accepted' /api/rs/internal/run/yield-forecast: post: tags: [Remote Sensing] summary: Trigger yield forecast run requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' responses: '202': $ref: '#/components/responses/Accepted' /api/rs/internal/water-stress/compute: post: tags: [Remote Sensing] summary: Compute or upsert water stress snapshot requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' responses: '200': $ref: '#/components/responses/Ok' /api/rs/internal/indices/compute: post: tags: [Remote Sensing] summary: Trigger remote index compute job requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/RSComputeExample' responses: '202': $ref: '#/components/responses/Accepted' /api/rs/internal/indices/jobs/{job_id}: get: tags: [Remote Sensing] summary: Get index compute job status parameters: - name: job_id in: path required: true schema: type: string responses: '200': $ref: '#/components/responses/Ok' /api/rs/internal/indices/jobs/{job_id}/phenology-report: get: tags: [Remote Sensing] summary: Get index job phenology report parameters: - name: job_id in: path required: true schema: type: string responses: '200': $ref: '#/components/responses/Ok' /api/alerts/rules/: get: tags: [Alerts] summary: List alert rules responses: '200': $ref: '#/components/responses/Ok' post: tags: [Alerts] summary: Create alert rule requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/AlertRuleCreateExample' responses: '201': $ref: '#/components/responses/Created' /api/alerts/rules/{object_id}: get: tags: [Alerts] summary: Get alert rule parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' put: tags: [Alerts] summary: Update alert rule parameters: - $ref: '#/components/parameters/ObjectId' requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/AlertRuleCreateExample' responses: '200': $ref: '#/components/responses/Ok' /api/alerts/rules/{object_id}/versions: get: tags: [Alerts] summary: List alert rule versions parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' /api/alerts/rules/{object_id}/rollback: post: tags: [Alerts] summary: Roll back alert rule version parameters: - $ref: '#/components/parameters/ObjectId' requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/AlertRuleRollbackExample' responses: '200': $ref: '#/components/responses/Ok' /api/alerts/alerts/: get: tags: [Alerts] summary: List alerts responses: '200': $ref: '#/components/responses/Ok' post: tags: [Alerts] summary: Create alert requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/AlertCreateExample' responses: '201': $ref: '#/components/responses/Created' /api/alerts/alerts/count-by-organization: get: tags: [Alerts] summary: Count alerts grouped by organization parameters: - name: tenant_id in: query required: true schema: type: string - name: status in: query required: false schema: type: string enum: [open, acknowledged, resolved, expired] responses: '200': $ref: '#/components/responses/Ok' /api/alerts/alerts/daily-summary: get: tags: [Alerts] summary: Get daily alert summary time series parameters: - name: tenant_id in: query required: true schema: type: string - name: days in: query required: false schema: type: integer minimum: 1 maximum: 365 responses: '200': $ref: '#/components/responses/Ok' /api/alerts/alerts/{object_id}: get: tags: [Alerts] summary: Get alert detail parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' /api/alerts/alerts/{object_id}/ack: post: tags: [Alerts] summary: Acknowledge alert parameters: - $ref: '#/components/parameters/ObjectId' requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/EmptyObjectExample' responses: '200': $ref: '#/components/responses/Ok' /api/alerts/alerts/{object_id}/resolve: post: tags: [Alerts] summary: Resolve alert parameters: - $ref: '#/components/parameters/ObjectId' requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/EmptyObjectExample' responses: '200': $ref: '#/components/responses/Ok' /api/alerts/parcels/{parcel_id}/alerts: get: tags: [Alerts] summary: List alerts for parcel parameters: - $ref: '#/components/parameters/ParcelId' responses: '200': $ref: '#/components/responses/Ok' /api/alerts/internal/evaluate/parcel/{parcel_id}: post: tags: [Alerts] summary: Evaluate alert for parcel description: Internal evaluation endpoint used by scheduled jobs and bridge flows. parameters: - $ref: '#/components/parameters/ParcelId' requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/AlertEvaluateExample' responses: '200': $ref: '#/components/responses/Ok' '201': $ref: '#/components/responses/Created' /api/alerts/internal/evaluate/scheduled: post: tags: [Alerts] summary: Run scheduled alert evaluation requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/ScheduledEvaluateExample' responses: '200': $ref: '#/components/responses/Ok' /api/alerts/internal/expire: post: tags: [Alerts] summary: Expire due alerts requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/EmptyObjectExample' responses: '200': $ref: '#/components/responses/Ok' /api/alerts/internal/retention/purge: post: tags: [Alerts] summary: Purge expired/resolved alert data by retention policy requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/RetentionPurgeExample' responses: '200': $ref: '#/components/responses/Ok' /api/notify/notifications/: get: tags: [Notifications] summary: List notification inbox entries responses: '200': $ref: '#/components/responses/Ok' post: tags: [Notifications] summary: Create notification inbox entry requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/NotificationCreateExample' responses: '201': $ref: '#/components/responses/Created' /api/notify/notifications/{object_id}: get: tags: [Notifications] summary: Get notification detail parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' put: tags: [Notifications] summary: Update notification state parameters: - $ref: '#/components/parameters/ObjectId' requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/NotificationUpdateExample' responses: '200': $ref: '#/components/responses/Ok' delete: tags: [Notifications] summary: Archive notification parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' /api/notify/preferences/: get: tags: [Notifications] summary: List notification preferences responses: '200': $ref: '#/components/responses/Ok' post: tags: [Notifications] summary: Create notification preference requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/NotificationPreferenceExample' responses: '201': $ref: '#/components/responses/Created' /api/notify/preferences/{object_id}: get: tags: [Notifications] summary: Get notification preference parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' put: tags: [Notifications] summary: Update notification preference parameters: - $ref: '#/components/parameters/ObjectId' requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/NotificationPreferenceExample' responses: '200': $ref: '#/components/responses/Ok' /api/notify/delivery-attempts/: get: tags: [Notifications] summary: List delivery attempts responses: '200': $ref: '#/components/responses/Ok' post: tags: [Notifications] summary: Create delivery attempt requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/DeliveryAttemptCreateExample' responses: '201': $ref: '#/components/responses/Created' /api/notify/delivery-attempts/{object_id}: get: tags: [Notifications] summary: Get delivery attempt detail parameters: - $ref: '#/components/parameters/ObjectId' responses: '200': $ref: '#/components/responses/Ok' /api/notify/internal/emit: post: tags: [Notifications] summary: Emit internal notification description: Internal notification enqueue endpoint. requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/NotificationEmitExample' responses: '200': $ref: '#/components/responses/Ok' '201': $ref: '#/components/responses/Created' /api/notify/internal/dispatch: post: tags: [Notifications] summary: Dispatch queued notifications requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/EmptyObjectExample' responses: '200': $ref: '#/components/responses/Ok' /api/notify/internal/retention/purge: post: tags: [Notifications] summary: Purge notification data by retention policy requestBody: content: application/json: schema: $ref: '#/components/schemas/GenericObject' examples: default: $ref: '#/components/examples/RetentionPurgeExample' responses: '200': $ref: '#/components/responses/Ok'