{"openapi":"3.0.3","info":{"title":"SolarScanner Public API","version":"1.0.0","description":"Server-to-server REST API for organizations on an active SolarScanner subscription.\n\nMint API keys via the portal (Organization Settings → API Keys).\nAuthentication: `Authorization: Bearer solarscanner_ai_<32 hex>`.\n\nSee `wiki/integrations/api-quickstart.md` for the 5-minute getting-started guide.\nSee `wiki/integrations/public-api-versioning.md` for the breaking-change policy.","contact":{"name":"SolarScanner support","email":"support@solarscanner.ai"}},"servers":[{"url":"https://solarscanner-production.up.railway.app","description":"Production"},{"url":"https://solarscanner-staging.up.railway.app","description":"Staging (internal)"}],"tags":[{"name":"Public API","description":"Server-to-server endpoints under /api/v1/public/*."}],"paths":{"/api/v1/public/leads":{"get":{"operationId":"getLeads","summary":"GET /api/v1/public/leads","tags":["Public API"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success — canonical envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"lead_source":{"type":"string"},"customer_email":{"nullable":true,"type":"string"},"customer_phone":{"nullable":true,"anyOf":[{"type":"string"},{"type":"number"}]},"first_name":{"nullable":true,"type":"string"},"last_name":{"nullable":true,"type":"string"},"property_address":{"nullable":true,"type":"string"},"property_type":{"nullable":true,"type":"string"},"system_size":{"nullable":true,"anyOf":[{"type":"string"},{"type":"number"}]},"system_value":{"nullable":true,"anyOf":[{"type":"string"},{"type":"number"}]},"estimate_metric":{"nullable":true,"type":"string"},"estimate_metric_last_updated":{"nullable":true,"type":"string"},"notes":{"nullable":true},"created_at":{"type":"string"}},"required":["id","lead_source","customer_email","customer_phone","first_name","last_name","property_address","property_type","system_size","system_value","estimate_metric","estimate_metric_last_updated","notes","created_at"],"additionalProperties":{}}},"next_cursor":{"nullable":true,"type":"string"},"request_id":{"type":"string","pattern":"^req_[0-9a-f]{24}$"}},"required":["data","next_cursor","request_id"]}}}},"400":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"410":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"parameters":[{"name":"cursor","in":"query","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","required":true,"schema":{"default":50,"type":"integer","minimum":1,"maximum":500}},{"name":"since","in":"query","required":false,"schema":{"type":"string"}}]}},"/api/v1/public/leads/{id}":{"get":{"operationId":"getLeadsById","summary":"GET /api/v1/public/leads/{id}","tags":["Public API"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success — canonical envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"lead_source":{"type":"string"},"customer_email":{"nullable":true,"type":"string"},"customer_phone":{"nullable":true,"anyOf":[{"type":"string"},{"type":"number"}]},"first_name":{"nullable":true,"type":"string"},"last_name":{"nullable":true,"type":"string"},"property_address":{"nullable":true,"type":"string"},"property_type":{"nullable":true,"type":"string"},"system_size":{"nullable":true,"anyOf":[{"type":"string"},{"type":"number"}]},"system_value":{"nullable":true,"anyOf":[{"type":"string"},{"type":"number"}]},"estimate_metric":{"nullable":true,"type":"string"},"estimate_metric_last_updated":{"nullable":true,"type":"string"},"notes":{"nullable":true},"created_at":{"type":"string"}},"required":["id","lead_source","customer_email","customer_phone","first_name","last_name","property_address","property_type","system_size","system_value","estimate_metric","estimate_metric_last_updated","notes","created_at"],"additionalProperties":{}},"request_id":{"type":"string","pattern":"^req_[0-9a-f]{24}$"}},"required":["data","request_id"]}}}},"400":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"410":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}]}},"/api/v1/public/account":{"get":{"operationId":"getAccount","summary":"GET /api/v1/public/account","tags":["Public API"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success — canonical envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"nullable":true,"type":"string"},"email":{"nullable":true,"type":"string"},"phone":{"nullable":true,"type":"string"},"address":{"nullable":true,"type":"string"},"license_number":{"nullable":true,"type":"string"},"logo_url":{"nullable":true,"type":"string"},"allowed_domains":{"nullable":true,"type":"array","items":{"type":"string"}},"enable_job_estimate_emails":{"nullable":true,"type":"boolean"},"is_subscription_active":{"type":"boolean"},"marketing_budgets":{"nullable":true},"type":{"nullable":true,"type":"string"},"closed_at":{"nullable":true,"type":"string"},"created_at":{"type":"string"},"updated_at":{"nullable":true,"type":"string"}},"required":["id","name","email","phone","address","license_number","logo_url","allowed_domains","enable_job_estimate_emails","is_subscription_active","marketing_budgets","type","closed_at","created_at","updated_at"],"additionalProperties":{}},"request_id":{"type":"string","pattern":"^req_[0-9a-f]{24}$"}},"required":["data","request_id"]}}}},"400":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"410":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/v1/public/webhook":{"get":{"operationId":"getWebhook","summary":"GET /api/v1/public/webhook","tags":["Public API"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success — canonical envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"webhook_url":{"nullable":true,"type":"string"},"configured":{"type":"boolean"},"webhook_secret_redacted":{"nullable":true,"type":"string"}},"required":["webhook_url","configured","webhook_secret_redacted"]},"request_id":{"type":"string","pattern":"^req_[0-9a-f]{24}$"}},"required":["data","request_id"]}}}},"400":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"410":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"put":{"operationId":"putWebhook","summary":"PUT /api/v1/public/webhook","tags":["Public API"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success — canonical envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"webhook_url":{"nullable":true,"type":"string"},"configured":{"type":"boolean"},"validated":{"type":"boolean"}},"required":["webhook_url","configured","validated"]},"request_id":{"type":"string","pattern":"^req_[0-9a-f]{24}$"}},"required":["data","request_id"]}}}},"400":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"410":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"parameters":[{"name":"test","in":"query","required":false,"schema":{"type":"string","enum":["true","false"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"webhook_url":{"anyOf":[{"type":"string"},{"type":"string","nullable":true,"enum":[null]}]}},"additionalProperties":{}}}}}}},"/api/v1/public/plugin-config":{"get":{"operationId":"getPluginConfig","summary":"GET /api/v1/public/plugin-config","tags":["Public API"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success — canonical envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"plugin_config":{"nullable":true}},"required":["plugin_config"]},"request_id":{"type":"string","pattern":"^req_[0-9a-f]{24}$"}},"required":["data","request_id"]}}}},"400":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"410":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/v1/public/webhook/test":{"post":{"operationId":"postWebhooktest","summary":"POST /api/v1/public/webhook/test","tags":["Public API"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success — canonical envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"webhook_url":{"type":"string"},"attempts":{"type":"integer","minimum":0,"exclusiveMinimum":true,"maximum":9007199254740991}},"required":["webhook_url","attempts"]},"request_id":{"type":"string","pattern":"^req_[0-9a-f]{24}$"}},"required":["data","request_id"]}}}},"400":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"410":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":false}}}}}},"/api/v1/public/webhook/secret/rotate":{"post":{"operationId":"postWebhooksecretrotate","summary":"POST /api/v1/public/webhook/secret/rotate","tags":["Public API"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success — canonical envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"webhook_secret":{"type":"string","pattern":"^whsec_[0-9a-f]{64}$"},"webhook_secret_redacted":{"type":"string","pattern":"^whsec_••••••••.{4}$"},"rotated_at":{"type":"string"}},"required":["webhook_secret","webhook_secret_redacted","rotated_at"]},"request_id":{"type":"string","pattern":"^req_[0-9a-f]{24}$"}},"required":["data","request_id"]}}}},"400":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"410":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":false}}}}}},"/api/v1/public/marketing-budgets":{"put":{"operationId":"putMarketingBudgets","summary":"PUT /api/v1/public/marketing-budgets","tags":["Public API"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success — canonical envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"marketing_budgets":{"type":"array","items":{"type":"object","properties":{"channel":{"type":"string","enum":["Paid Search","Paid Social","Paid Video","Paid Shopping","Display","Paid Unknown"]},"monthly_budget":{"type":"number","minimum":0}},"required":["channel","monthly_budget"]}}},"required":["marketing_budgets"]},"request_id":{"type":"string","pattern":"^req_[0-9a-f]{24}$"}},"required":["data","request_id"]}}}},"400":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"410":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"marketing_budgets":{"maxItems":6,"type":"array","items":{"type":"object","properties":{"channel":{"type":"string","enum":["Paid Search","Paid Social","Paid Video","Paid Shopping","Display","Paid Unknown"]},"monthly_budget":{"type":"number","minimum":0}},"required":["channel","monthly_budget"],"additionalProperties":false}}},"required":["marketing_budgets"],"additionalProperties":false}}}}}},"/api/v1/public/leads/{id}/notes":{"post":{"operationId":"postLeadsByIdnotes","summary":"POST /api/v1/public/leads/{id}/notes","tags":["Public API"],"security":[{"bearerAuth":[]}],"responses":{"201":{"description":"Success — canonical envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"note":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"body":{"type":"string","minLength":1,"maxLength":5000},"author":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["user"]},"email":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"}},"required":["type","email"]},{"type":"object","properties":{"type":{"type":"string","enum":["api_key"]},"api_key_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"api_key_name":{"type":"string","minLength":1}},"required":["type","api_key_id","api_key_name"]}]},"created_at":{"type":"string"}},"required":["id","body","author","created_at"]}},"required":["note"]},"request_id":{"type":"string","pattern":"^req_[0-9a-f]{24}$"}},"required":["data","request_id"]}}}},"400":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"410":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"body":{"type":"string","minLength":1,"maxLength":5000}},"required":["body"],"additionalProperties":false}}}}}},"/api/v1/public/plugin-config/pricing":{"patch":{"operationId":"patchPluginConfigpricing","summary":"PATCH /api/v1/public/plugin-config/pricing","tags":["Public API"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Success — canonical envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"plugin_config":{"nullable":true}},"required":["plugin_config"]},"request_id":{"type":"string","pattern":"^req_[0-9a-f]{24}$"}},"required":["data","request_id"]}}}},"400":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"401":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"410":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"500":{"description":"Canonical error envelope (server--040 M1.C).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"cost_ppw":{"minItems":1,"type":"array","items":{"type":"object","properties":{"minKw":{"type":"number","minimum":0},"maxKw":{"nullable":true,"type":"number","minimum":0,"exclusiveMinimum":true},"ppw":{"type":"number","minimum":0,"exclusiveMinimum":true}},"required":["minKw","maxKw","ppw"],"additionalProperties":false}},"incentives":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"unit":{"type":"string","enum":["%","$","$/kW"]},"value":{"type":"number"},"projectType":{"type":"string","enum":["residential","commercial","both"]},"calculationBase":{"type":"string","enum":["total","adjusted"]},"maxAmount":{"nullable":true,"type":"number","minimum":0,"exclusiveMinimum":true},"expiryDate":{"nullable":true,"type":"string"},"minKw":{"nullable":true,"type":"number","minimum":0,"exclusiveMinimum":true},"maxKw":{"nullable":true,"type":"number","minimum":0,"exclusiveMinimum":true}},"required":["name","unit","value","projectType","calculationBase"],"additionalProperties":false}}},"required":["cost_ppw","incentives"],"additionalProperties":false}}}}}}},"components":{"schemas":{"ErrorCode":{"type":"string","enum":["INVALID_PREFIX","KEY_NOT_FOUND","KEY_REVOKED","SUBSCRIPTION_INACTIVE","ORG_CLOSED","VALIDATION_FAILED","IDEMPOTENCY_KEY_CONFLICT","RATE_LIMIT_EXCEEDED","NOT_FOUND","LEAD_NOT_FOUND","NOTE_CAP_REACHED"],"description":"Canonical error code enum. Adding a value is a breaking change to the API surface; pin in tests. Source: PUBLIC_API_ERROR_CODES in src/schemas/publicApi.js."},"ErrorEnvelope":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"$ref":"#/components/schemas/ErrorCode"},"message":{"type":"string","minLength":1},"details":{}},"required":["code","message"],"additionalProperties":false},"request_id":{"type":"string","pattern":"^req_[0-9a-f]{24}$"},"timestamp":{"type":"string"}},"required":["error","request_id","timestamp"],"additionalProperties":false},"NoteAuthor":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["user"]},"email":{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"}},"required":["type","email"]},{"type":"object","properties":{"type":{"type":"string","enum":["api_key"]},"api_key_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"api_key_name":{"type":"string","minLength":1}},"required":["type","api_key_id","api_key_name"]}],"discriminator":{"propertyName":"type"}}},"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"solarscanner_ai_<32 hex>","description":"Public-API bearer token minted via the portal (POST /api/v1/organization/api-keys). One-time-reveal on creation; subsequent reads return only the prefix preview. Revoke via DELETE /api/v1/organization/api-keys/{id}."}}}}